source: translator/Parser/ExpressionNode.cc@ a0d9f94

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors ctor deferred_resn demangler enum forall-pointer-decay gc_noraii jacob/cs343-translation jenkins-sandbox memory new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new string with_gc
Last change on this file since a0d9f94 was 51b73452, checked in by Peter A. Buhr <pabuhr@…>, 11 years ago

initial commit

  • Property mode set to 100644
File size: 20.2 KB
Line 
1/* -*- C++ -*- */
2#include <cassert>
3#include <cctype>
4#include <algorithm>
5
6#include "ParseNode.h"
7#include "SynTree/Type.h"
8#include "SynTree/Constant.h"
9#include "SynTree/Expression.h"
10#include "SynTree/Declaration.h"
11#include "UnimplementedError.h"
12#include "parseutility.h"
13#include "utility.h"
14
15using namespace std;
16
17ExpressionNode::ExpressionNode() : ParseNode(), argName( 0 ) {
18}
19
20ExpressionNode::ExpressionNode(string *name_) : ParseNode( *name_ ), argName( 0 ) {
21 delete name_;
22}
23
24ExpressionNode::ExpressionNode( const ExpressionNode &other )
25 : ParseNode( other.name )
26{
27 if( other.argName ) {
28 argName = other.argName->clone();
29 } else {
30 argName = 0;
31 }
32}
33
34ExpressionNode * ExpressionNode::set_asArgName( std::string *aName ) {
35 argName = new VarRefNode(aName);
36 return this;
37}
38
39ExpressionNode * ExpressionNode::set_asArgName( ExpressionNode *aDesignator ) {
40 argName = aDesignator;
41 return this;
42}
43
44void ExpressionNode::printDesignation( std::ostream &os, int indent ) const {
45 if( argName ) {
46 os << string(' ', indent) << "(designated by: ";
47 argName->printOneLine(os, indent );
48 os << ")" << std::endl;
49 }
50}
51
52NullExprNode::NullExprNode()
53{
54}
55
56NullExprNode *
57NullExprNode::clone() const
58{
59 return new NullExprNode();
60}
61
62void
63NullExprNode::print(std::ostream & os, int indent) const
64{
65 printDesignation(os);
66 os << "null expression";
67}
68
69void
70NullExprNode::printOneLine(std::ostream & os, int indent) const
71{
72 printDesignation(os);
73 os << "null";
74}
75
76Expression *
77NullExprNode::build() const
78{
79 return 0;
80}
81
82CommaExprNode *ExpressionNode::add_to_list(ExpressionNode *exp){
83 return new CommaExprNode(this, exp );
84}
85
86// enum ConstantNode::Type = { Integer, Float, Character, String, Range }
87
88ConstantNode::ConstantNode(void) :
89 ExpressionNode(), sign(true), longs(0), size(0)
90{}
91
92ConstantNode::ConstantNode(string *name_) :
93 ExpressionNode(name_), sign(true), longs(0), size(0)
94{}
95
96ConstantNode::ConstantNode(Type t, string *inVal) :
97 type(t), sign(true), longs(0), size(0)
98{
99 if( inVal ) {
100 value = *inVal;
101 delete inVal;
102 } else {
103 value = "";
104 }
105
106 classify(value);
107}
108
109ConstantNode::ConstantNode( const ConstantNode &other )
110 : ExpressionNode( other ), type( other.type ), value( other.value ), sign( other.sign ), base( other.base ), longs( other.longs ), size( other.size )
111{
112}
113
114// for some reason, std::tolower doesn't work as an argument to std::transform in g++ 3.1
115inline char
116tolower_hack( char c )
117{
118 return std::tolower( c );
119}
120
121void ConstantNode::classify(std::string &str){
122 switch(type){
123 case Integer:
124 case Float:
125 {
126 std::string sfx("");
127 char c;
128 int i = str.length() - 1;
129
130 while( i >= 0 && !isxdigit(c = str.at(i--)) )
131 sfx += c;
132
133 value = str.substr( 0, i + 2 );
134
135 // get rid of underscores
136 value.erase(remove(value.begin(), value.end(), '_'), value.end());
137
138 std::transform(sfx.begin(), sfx.end(), sfx.begin(), tolower_hack);
139
140 if( sfx.find("ll") != string::npos ){
141 longs = 2;
142 } else if (sfx.find("l") != string::npos ){
143 longs = 1;
144 }
145
146 assert((longs >= 0) && (longs <= 2));
147
148 if( sfx.find("u") != string::npos )
149 sign = false;
150
151 break;
152 }
153 case Character:
154 {
155 // remove underscores from hex and oct escapes
156 if(str.substr(1,2) == "\\x")
157 value.erase(remove(value.begin(), value.end(), '_'), value.end());
158
159 break;
160 }
161 default:
162 // shouldn't be here
163 ;
164 }
165}
166
167ConstantNode::Type ConstantNode::get_type(void) const {
168 return type;
169}
170
171ConstantNode*
172ConstantNode::append( std::string *newValue )
173{
174 if( newValue ) {
175 if (type == String){
176 std::string temp = *newValue;
177 value.resize( value.size() - 1 );
178 value += newValue->substr(1, newValue->size());
179 } else
180 value += *newValue;
181
182 delete newValue;
183 }
184 return this;
185}
186
187void ConstantNode::printOneLine(std::ostream &os, int indent ) const
188{
189 os << string(indent, ' ');
190 printDesignation(os);
191
192 switch( type ) {
193 /* integers */
194 case Integer:
195 os << value ;
196 break;
197 case Float:
198 os << value ;
199 break;
200
201 case Character:
202 os << "'" << value << "'";
203 break;
204
205 case String:
206 os << '"' << value << '"';
207 break;
208 }
209
210 os << ' ';
211}
212
213void ConstantNode::print(std::ostream &os, int indent ) const
214{
215 printOneLine( os, indent );
216 os << endl;
217}
218
219Expression *ConstantNode::build() const {
220 ::Type::Qualifiers q;
221 BasicType *bt;
222
223 switch(get_type()){
224 case Integer:
225 /* Cfr. standard 6.4.4.1 */
226 //bt.set_kind(BasicType::SignedInt);
227 bt = new BasicType(q, BasicType::SignedInt);
228 break;
229
230 case Float:
231 bt = new BasicType(q, BasicType::Float);
232 break;
233
234 case Character:
235 bt = new BasicType(q, BasicType::Char);
236 break;
237
238 case String:
239 // string should probably be a primitive type
240 ArrayType *at;
241 std::string value = get_value();
242 at = new ArrayType(q, new BasicType(q, BasicType::Char),
243 new ConstantExpr( Constant( new BasicType(q, BasicType::SignedInt),
244 toString( value.size() - 1 ) ) ), // account for '\0'
245 false, false );
246
247 return new ConstantExpr( Constant(at, value), maybeBuild< Expression >( get_argName() ) );
248 }
249
250 return new ConstantExpr( Constant(bt, get_value()), maybeBuild< Expression >( get_argName() ) );
251}
252
253
254VarRefNode::VarRefNode() : isLabel(false) {}
255
256VarRefNode::VarRefNode(string *name_, bool labelp) :
257 ExpressionNode(name_), isLabel(labelp) {}
258
259VarRefNode::VarRefNode( const VarRefNode &other )
260 : ExpressionNode( other ), isLabel( other.isLabel )
261{
262}
263
264Expression *VarRefNode::build() const {
265 return new NameExpr( get_name(), maybeBuild< Expression >( get_argName() ) );
266}
267
268void VarRefNode::printOneLine(std::ostream &os, int indent ) const {
269 printDesignation(os);
270 os << get_name() << ' ';
271}
272
273void VarRefNode::print(std::ostream &os, int indent ) const {
274 printDesignation(os);
275 os << '\r' << string(indent, ' ') << "Referencing: ";
276
277 os << "Variable: " << get_name();
278
279 os << endl;
280}
281
282
283OperatorNode::OperatorNode(Type t):type(t) {}
284
285OperatorNode::OperatorNode( const OperatorNode &other )
286 : ExpressionNode( other ), type( other.type )
287{
288}
289
290OperatorNode::~OperatorNode() {}
291
292OperatorNode::Type OperatorNode::get_type(void) const{
293 return type;
294}
295
296void OperatorNode::printOneLine( std::ostream &os, int indent ) const
297{
298 printDesignation(os);
299 os << OpName[ type ] << ' ';
300}
301
302void OperatorNode::print( std::ostream &os, int indent ) const{
303 printDesignation(os);
304 os << '\r' << string(indent, ' ') << "Operator: " << OpName[type] << endl;
305
306 return;
307}
308
309std::string OperatorNode::get_typename(void) const{
310 return string(OpName[ type ]);
311}
312
313const char *OperatorNode::OpName[] =
314 { "TupleC", "Comma", "TupleFieldSel",// "TuplePFieldSel", //n-adic
315 // triadic
316 "Cond", "NCond",
317 // diadic
318 "SizeOf", "AlignOf", "Attr", "CompLit", "Plus", "Minus", "Mul", "Div", "Mod", "Or",
319 "And", "BitOr", "BitAnd", "Xor", "Cast", "LShift", "RShift", "LThan", "GThan",
320 "LEThan", "GEThan", "Eq", "Neq", "Assign", "MulAssn", "DivAssn", "ModAssn", "PlusAssn",
321 "MinusAssn", "LSAssn", "RSAssn", "AndAssn", "ERAssn", "OrAssn", "Index", "FieldSel","PFieldSel",
322 "Range",
323 // monadic
324 "UnPlus", "UnMinus", "AddressOf", "PointTo", "Neg", "BitNeg", "Incr", "IncrPost", "Decr", "DecrPost", "LabelAddress"
325 };
326
327CompositeExprNode::CompositeExprNode(void) : ExpressionNode(), function( 0 ), arguments( 0 ) {
328}
329
330CompositeExprNode::CompositeExprNode(string *name_) : ExpressionNode(name_), function( 0 ), arguments( 0 )
331{
332}
333
334CompositeExprNode::CompositeExprNode(ExpressionNode *f, ExpressionNode *args):
335 function(f), arguments(args) {
336}
337
338CompositeExprNode::CompositeExprNode(ExpressionNode *f, ExpressionNode *arg1, ExpressionNode *arg2):
339 function(f), arguments(arg1) {
340 arguments->set_link(arg2);
341}
342
343CompositeExprNode::CompositeExprNode( const CompositeExprNode &other )
344 : ExpressionNode( other ), function( maybeClone( other.function ) )
345{
346 ParseNode *cur = other.arguments;
347 while( cur ) {
348 if( arguments ) {
349 arguments->set_link( cur->clone() );
350 } else {
351 arguments = (ExpressionNode*)cur->clone();
352 }
353 cur = cur->get_link();
354 }
355}
356
357CompositeExprNode::~CompositeExprNode()
358{
359 delete function;
360 delete arguments;
361}
362
363// the names that users use to define operator functions
364static const char *opFuncName[] =
365 { "", "", "",
366 "", "",
367 // diadic
368 "", "", "", "", "?+?", "?-?", "?*?", "?/?", "?%?", "", "",
369 "?|?", "?&?", "?^?", "", "?<<?", "?>>?", "?<?", "?>?", "?<=?",
370 "?>=?", "?==?", "?!=?", "?=?", "?*=?", "?/=?", "?%=?", "?+=?", "?-=?",
371 "?<<=?", "?>>=?", "?&=?", "?^=?", "?|=?", "?[?]", "","","Range",
372 // monadic
373 "+?", "-?", "", "*?", "!?", "~?", "++?", "?++", "--?", "?--", "LabAddress"
374 };
375
376#include "utility.h"
377Expression *CompositeExprNode::build() const {
378 OperatorNode *op;
379 std::list<Expression *> args;
380
381 buildList(get_args(), args);
382
383 if (!( op = dynamic_cast<OperatorNode *>(function)) ){
384 // a function as opposed to an operator
385 return new UntypedExpr(function->build(), args, maybeBuild< Expression >( get_argName() ));
386
387 } else {
388
389 switch(op->get_type()){
390 case OperatorNode::Incr:
391 case OperatorNode::Decr:
392 case OperatorNode::IncrPost:
393 case OperatorNode::DecrPost:
394 case OperatorNode::Assign:
395 case OperatorNode::MulAssn:
396 case OperatorNode::DivAssn:
397 case OperatorNode::ModAssn:
398 case OperatorNode::PlusAssn:
399 case OperatorNode::MinusAssn:
400 case OperatorNode::LSAssn:
401 case OperatorNode::RSAssn:
402 case OperatorNode::AndAssn:
403 case OperatorNode::ERAssn:
404 case OperatorNode::OrAssn:
405 // the rewrite rules for these expressions specify that the first argument has its address taken
406 assert( !args.empty() );
407 args.front() = new AddressExpr( args.front() );
408 break;
409
410 default:
411 /* do nothing */
412 ;
413 }
414
415 switch(op->get_type()){
416
417 case OperatorNode::Incr:
418 case OperatorNode::Decr:
419 case OperatorNode::IncrPost:
420 case OperatorNode::DecrPost:
421 case OperatorNode::Assign:
422 case OperatorNode::MulAssn:
423 case OperatorNode::DivAssn:
424 case OperatorNode::ModAssn:
425 case OperatorNode::PlusAssn:
426 case OperatorNode::MinusAssn:
427 case OperatorNode::LSAssn:
428 case OperatorNode::RSAssn:
429 case OperatorNode::AndAssn:
430 case OperatorNode::ERAssn:
431 case OperatorNode::OrAssn:
432 case OperatorNode::Plus:
433 case OperatorNode::Minus:
434 case OperatorNode::Mul:
435 case OperatorNode::Div:
436 case OperatorNode::Mod:
437 case OperatorNode::BitOr:
438 case OperatorNode::BitAnd:
439 case OperatorNode::Xor:
440 case OperatorNode::LShift:
441 case OperatorNode::RShift:
442 case OperatorNode::LThan:
443 case OperatorNode::GThan:
444 case OperatorNode::LEThan:
445 case OperatorNode::GEThan:
446 case OperatorNode::Eq:
447 case OperatorNode::Neq:
448 case OperatorNode::Index:
449 case OperatorNode::Range:
450 case OperatorNode::UnPlus:
451 case OperatorNode::UnMinus:
452 case OperatorNode::PointTo:
453 case OperatorNode::Neg:
454 case OperatorNode::BitNeg:
455 case OperatorNode::LabelAddress:
456 return new UntypedExpr( new NameExpr( opFuncName[ op->get_type() ] ), args );
457
458 case OperatorNode::AddressOf:
459 assert( args.size() == 1 );
460 assert( args.front() );
461
462 return new AddressExpr( args.front() );
463
464 case OperatorNode::Cast:
465 {
466 TypeValueNode * arg = dynamic_cast<TypeValueNode *>(get_args());
467 assert( arg );
468
469 DeclarationNode *decl_node = arg->get_decl();
470 ExpressionNode *expr_node = dynamic_cast<ExpressionNode *>(arg->get_link());
471
472 Type *targetType = decl_node->buildType();
473 if( dynamic_cast< VoidType* >( targetType ) ) {
474 delete targetType;
475 return new CastExpr( expr_node->build(), maybeBuild< Expression >( get_argName() ) );
476 } else {
477 return new CastExpr(expr_node->build(),targetType, maybeBuild< Expression >( get_argName() ) );
478 }
479 }
480
481 case OperatorNode::FieldSel:
482 {
483 assert( args.size() == 2 );
484
485 NameExpr *member = dynamic_cast<NameExpr *>(args.back());
486 // TupleExpr *memberTup = dynamic_cast<TupleExpr *>(args.back());
487
488 if ( member != 0 )
489 {
490 UntypedMemberExpr *ret = new UntypedMemberExpr(member->get_name(), args.front());
491 delete member;
492 return ret;
493 }
494 /* else if ( memberTup != 0 )
495 {
496 UntypedMemberExpr *ret = new UntypedMemberExpr(memberTup->get_name(), args.front());
497 delete member;
498 return ret;
499 } */
500 else
501 assert( false );
502 }
503
504 case OperatorNode::PFieldSel:
505 {
506 assert( args.size() == 2 );
507
508 NameExpr *member = dynamic_cast<NameExpr *>(args.back()); // modify for Tuples xxx
509 assert( member != 0 );
510
511 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
512 deref->get_args().push_back( args.front() );
513
514 UntypedMemberExpr *ret = new UntypedMemberExpr(member->get_name(), deref);
515 delete member;
516 return ret;
517 }
518
519 case OperatorNode::AlignOf:
520 case OperatorNode::SizeOf:
521 {
522/// bool isSizeOf = (op->get_type() == OperatorNode::SizeOf);
523
524 if( TypeValueNode * arg = dynamic_cast<TypeValueNode *>(get_args()) ) {
525 return new SizeofExpr(arg->get_decl()->buildType());
526 } else {
527 return new SizeofExpr(args.front());
528 }
529 }
530
531 case OperatorNode::Attr:
532 {
533 VarRefNode *var = dynamic_cast<VarRefNode *>(get_args());
534 assert( var );
535 if( !get_args()->get_link() ) {
536 return new AttrExpr(var->build(), (Expression*)0);
537 } else if( TypeValueNode * arg = dynamic_cast<TypeValueNode *>(get_args()->get_link()) ) {
538 return new AttrExpr(var->build(), arg->get_decl()->buildType());
539 } else {
540 return new AttrExpr(var->build(), args.back());
541 }
542 }
543
544
545 case OperatorNode::CompLit:
546 throw UnimplementedError( "C99 compound literals" );
547
548 // the short-circuited operators
549 case OperatorNode::Or:
550 case OperatorNode::And:
551 assert(args.size() == 2);
552 return new LogicalExpr( notZeroExpr( args.front() ), notZeroExpr( args.back() ), (op->get_type() == OperatorNode::And) );
553
554 case OperatorNode::Cond:
555 {
556 assert(args.size() == 3);
557 std::list< Expression* >::const_iterator i = args.begin();
558 Expression *arg1 = notZeroExpr( *i++ );
559 Expression *arg2 = *i++;
560 Expression *arg3 = *i++;
561 return new ConditionalExpr( arg1, arg2, arg3 );
562 }
563
564 case OperatorNode::NCond:
565 throw UnimplementedError( "GNU 2-argument conditional expression" );
566
567 case OperatorNode::Comma:
568 {
569 assert(args.size() == 2);
570 std::list< Expression* >::const_iterator i = args.begin();
571 Expression *ret = *i++;
572 while( i != args.end() ) {
573 ret = new CommaExpr( ret, *i++ );
574 }
575 return ret;
576 }
577
578 // Tuples
579 case OperatorNode::TupleC:
580 {
581 TupleExpr *ret = new TupleExpr();
582 std::copy( args.begin(), args.end(), back_inserter( ret->get_exprs() ) );
583 return ret;
584 }
585
586 default:
587 // shouldn't happen
588 return 0;
589 }
590 }
591}
592
593void CompositeExprNode::printOneLine(std::ostream &os, int indent) const
594{
595 printDesignation(os);
596 os << "( ";
597 function->printOneLine( os, indent );
598 for( ExpressionNode *cur = arguments; cur != 0; cur = dynamic_cast< ExpressionNode* >( cur->get_link() ) ) {
599 cur->printOneLine( os, indent );
600 }
601 os << ") ";
602}
603
604void CompositeExprNode::print(std::ostream &os, int indent) const
605{
606 printDesignation(os);
607 os << '\r' << string(indent, ' ') << "Application of: " << endl;
608 function->print( os, indent + ParseNode::indent_by );
609
610 os << '\r' << string(indent, ' ') ;
611 if( arguments ) {
612 os << "... on arguments: " << endl;
613 arguments->printList(os, indent + ParseNode::indent_by);
614 } else
615 os << "... on no arguments: " << endl;
616}
617
618void CompositeExprNode::set_function(ExpressionNode *f){
619 function = f;
620}
621
622void CompositeExprNode::set_args(ExpressionNode *args){
623 arguments = args;
624}
625
626ExpressionNode *CompositeExprNode::get_function(void) const {
627 return function;
628}
629
630ExpressionNode *CompositeExprNode::get_args(void) const {
631 return arguments;
632}
633
634void CompositeExprNode::add_arg(ExpressionNode *arg){
635 if(arguments)
636 arguments->set_link(arg);
637 else
638 set_args(arg);
639}
640
641CommaExprNode::CommaExprNode(): CompositeExprNode(new OperatorNode(OperatorNode::Comma)) {}
642
643CommaExprNode::CommaExprNode(ExpressionNode *exp)
644 : CompositeExprNode( new OperatorNode(OperatorNode::Comma), exp )
645 {
646 }
647
648CommaExprNode::CommaExprNode(ExpressionNode *exp1, ExpressionNode *exp2)
649 : CompositeExprNode(new OperatorNode(OperatorNode::Comma), exp1, exp2)
650{
651}
652
653CommaExprNode *CommaExprNode::add_to_list(ExpressionNode *exp){
654 add_arg(exp);
655
656 return this;
657}
658
659CommaExprNode::CommaExprNode( const CommaExprNode &other )
660 : CompositeExprNode( other )
661{
662}
663
664ValofExprNode::ValofExprNode(StatementNode *s): body(s) {}
665
666ValofExprNode::ValofExprNode( const ValofExprNode &other )
667 : ExpressionNode( other ), body( maybeClone( body ) )
668{
669}
670
671ValofExprNode::~ValofExprNode() {
672 delete body;
673}
674
675void ValofExprNode::print( std::ostream &os, int indent ) const {
676 printDesignation(os);
677 os << string(indent, ' ') << "Valof Expression:" << std::endl;
678 get_body()->print(os, indent + 4);
679}
680
681void ValofExprNode::printOneLine( std::ostream &, int indent ) const
682{
683 assert( false );
684}
685
686Expression *ValofExprNode::build() const {
687 return new UntypedValofExpr ( get_body()->build(), maybeBuild< Expression >( get_argName() ) );
688}
689
690ForCtlExprNode::ForCtlExprNode(ParseNode *init_, ExpressionNode *cond, ExpressionNode *incr)
691 throw (SemanticError)
692 : condition(cond), change(incr)
693{
694 if(init_ == 0)
695 init = 0;
696 else {
697 DeclarationNode *decl;
698 ExpressionNode *exp;
699
700 if((decl = dynamic_cast<DeclarationNode *>(init_)) != 0)
701 init = new StatementNode(decl);
702 else if((exp = dynamic_cast<ExpressionNode *>(init_)) != 0)
703 init = new StatementNode(StatementNode::Exp, exp);
704 else
705 throw SemanticError("Error in for control expression");
706 }
707}
708
709ForCtlExprNode::ForCtlExprNode( const ForCtlExprNode &other )
710 : ExpressionNode( other ), init( maybeClone( other.init ) ), condition( maybeClone( other.condition ) ), change( maybeClone( other.change ) )
711{
712}
713
714ForCtlExprNode::~ForCtlExprNode(){
715 delete init;
716 delete condition;
717 delete change;
718}
719
720Expression *ForCtlExprNode::build() const {
721 // this shouldn't be used!
722 assert( false );
723 return 0;
724}
725
726void ForCtlExprNode::print( std::ostream &os, int indent ) const{
727 os << string(indent,' ') << "For Control Expression -- : " << endl;
728
729 os << "\r" << string(indent + 2,' ') << "initialization: ";
730 if(init != 0)
731 init->print(os, indent + 4);
732
733 os << "\n\r" << string(indent + 2,' ') << "condition: ";
734 if(condition != 0)
735 condition->print(os, indent + 4);
736 os << "\n\r" << string(indent + 2,' ') << "increment: ";
737 if(change != 0)
738 change->print(os, indent + 4);
739}
740
741void
742ForCtlExprNode::printOneLine( std::ostream &, int indent ) const
743{
744 assert( false );
745}
746
747TypeValueNode::TypeValueNode(DeclarationNode *decl)
748 : decl( decl )
749{
750}
751
752TypeValueNode::TypeValueNode( const TypeValueNode &other )
753 : ExpressionNode( other ), decl( maybeClone( other.decl ) )
754{
755}
756
757Expression *
758TypeValueNode::build() const
759{
760 return new TypeExpr( decl->buildType() );
761}
762
763void
764TypeValueNode::print(std::ostream &os, int indent) const
765{
766 os << std::string( indent, ' ' ) << "Type:";
767 get_decl()->print(os, indent + 2);
768}
769
770void
771TypeValueNode::printOneLine(std::ostream &os, int indent) const
772{
773 os << "Type:";
774 get_decl()->print(os, indent + 2);
775}
776
777ExpressionNode *flattenCommas( ExpressionNode *list )
778{
779 if( CompositeExprNode *composite = dynamic_cast< CompositeExprNode * >( list ) )
780 {
781 OperatorNode *op;
782 if ( (op = dynamic_cast< OperatorNode * >( composite->get_function() )) && (op->get_type() == OperatorNode::Comma) )
783 {
784 if ( ExpressionNode *next = dynamic_cast< ExpressionNode * >( list->get_link() ) )
785 composite->add_arg( next );
786 return flattenCommas( composite->get_args() );
787 }
788 }
789
790 if ( ExpressionNode *next = dynamic_cast< ExpressionNode * >( list->get_link() ) )
791 list->set_next( flattenCommas( next ) );
792
793 return list;
794}
795
796ExpressionNode *tupleContents( ExpressionNode *tuple )
797{
798 if( CompositeExprNode *composite = dynamic_cast< CompositeExprNode * >( tuple ) ) {
799 OperatorNode *op = 0;
800 if ( (op = dynamic_cast< OperatorNode * >( composite->get_function() )) && (op->get_type() == OperatorNode::TupleC) )
801 return composite->get_args();
802 }
803 return tuple;
804}
Note: See TracBrowser for help on using the repository browser.