source: translator/Parser/ExpressionNode.cc@ d4778a6

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 d4778a6 was bdd516a, checked in by Peter A. Buhr <pabuhr@…>, 11 years ago

fixed sizeof type variable, find lowest cost alternative for sizeof expression, removed unused classes, added compiler flag, remove temporary file for -CFA, formatting

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