source: translator/Parser/ExpressionNode.cc @ bdd516a

aaron-thesisarm-ehcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newstringwith_gc
Last change on this file since bdd516a was bdd516a, checked in by Peter A. Buhr <pabuhr@…>, 8 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.