source: translator/Parser/ExpressionNode.cc @ 3848e0e

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newstringwith_gc
Last change on this file since 3848e0e was 3848e0e, checked in by Peter A. Buhr <pabuhr@…>, 9 years ago

underscore changes, ptrdiff_t changes, formating, _Bool prelude

  • Property mode set to 100644
File size: 20.0 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    }
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    }
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    }
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            }
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    }
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        }
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                }
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                    {
437                        UntypedMemberExpr *ret = new UntypedMemberExpr(member->get_name(), args.front());
438                        delete member;
439                        return ret;
440                    }
441                /* else if ( memberTup != 0 )
442                   {
443                   UntypedMemberExpr *ret = new UntypedMemberExpr(memberTup->get_name(), args.front());
444                   delete member;
445                   return ret;
446                   } */
447                else
448                    assert( false );
449            }
450          case OperatorNode::PFieldSel:
451            {
452                assert( args.size() == 2 );
453
454                NameExpr *member = dynamic_cast<NameExpr *>(args.back());  // modify for Tuples   xxx
455                assert( member != 0 );
456
457                UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
458                deref->get_args().push_back( args.front() );
459
460                UntypedMemberExpr *ret = new UntypedMemberExpr(member->get_name(), deref);
461                delete member;
462                return ret;
463            }
464          case OperatorNode::AlignOf:
465          case OperatorNode::SizeOf:
466            {
467///     bool isSizeOf = (op->get_type() == OperatorNode::SizeOf);
468
469                if ( TypeValueNode * arg = dynamic_cast<TypeValueNode *>(get_args()) ) {
470                    return new SizeofExpr(arg->get_decl()->buildType());
471                } else {
472                    return new SizeofExpr(args.front());
473                }
474            }
475          case OperatorNode::Attr:
476            {
477                VarRefNode *var = dynamic_cast<VarRefNode *>(get_args());
478                assert( var );
479                if ( !get_args()->get_link() ) {
480                    return new AttrExpr(var->build(), (Expression*)0);
481                } else if ( TypeValueNode * arg = dynamic_cast<TypeValueNode *>(get_args()->get_link()) ) {
482                    return new AttrExpr(var->build(), arg->get_decl()->buildType());
483                } else {
484                    return new AttrExpr(var->build(), args.back());
485                }
486            }
487          case OperatorNode::CompLit:
488            throw UnimplementedError( "C99 compound literals" );
489            // the short-circuited operators
490          case OperatorNode::Or:
491          case OperatorNode::And:
492            assert(args.size() == 2);
493            return new LogicalExpr( notZeroExpr( args.front() ), notZeroExpr( args.back() ), (op->get_type() == OperatorNode::And) );
494          case OperatorNode::Cond:
495            {
496                assert(args.size() == 3);
497                std::list< Expression* >::const_iterator i = args.begin();
498                Expression *arg1 = notZeroExpr( *i++ );
499                Expression *arg2 = *i++;
500                Expression *arg3 = *i++;
501                return new ConditionalExpr( arg1, arg2, arg3 );
502            }
503          case OperatorNode::NCond:
504            throw UnimplementedError( "GNU 2-argument conditional expression" );
505          case OperatorNode::Comma:
506            {
507                assert(args.size() == 2);
508                std::list< Expression* >::const_iterator i = args.begin();
509                Expression *ret = *i++;
510                while ( i != args.end() ) {
511                    ret = new CommaExpr( ret, *i++ );
512                }
513                return ret;
514            }
515            // Tuples
516          case OperatorNode::TupleC:
517            {
518                TupleExpr *ret = new TupleExpr();
519                std::copy( args.begin(), args.end(), back_inserter( ret->get_exprs() ) );
520                return ret;
521            }
522          default:
523            // shouldn't happen
524            return 0;
525        }
526    }
527}
528
529void CompositeExprNode::printOneLine(std::ostream &os, int indent) const {
530    printDesignation(os);
531    os << "( ";
532    function->printOneLine( os, indent );
533    for( ExpressionNode *cur = arguments; cur != 0; cur = dynamic_cast< ExpressionNode* >( cur->get_link() ) ) {
534        cur->printOneLine( os, indent );
535    }
536    os << ") ";
537}
538
539void CompositeExprNode::print(std::ostream &os, int indent) const {
540    printDesignation(os);
541    os << '\r' << string(indent, ' ') << "Application of: " << endl;
542    function->print( os, indent + ParseNode::indent_by );
543
544    os << '\r' << string(indent, ' ') ;
545    if ( arguments ) {
546        os << "... on arguments: " << endl;
547        arguments->printList(os, indent + ParseNode::indent_by);
548    } else
549        os << "... on no arguments: " << endl;
550}
551
552void CompositeExprNode::set_function(ExpressionNode *f){
553    function = f;
554}
555
556void CompositeExprNode::set_args(ExpressionNode *args){
557    arguments = args;
558}
559
560ExpressionNode *CompositeExprNode::get_function(void) const {
561    return function;
562}
563
564ExpressionNode *CompositeExprNode::get_args(void) const {
565    return arguments;
566}
567
568void CompositeExprNode::add_arg(ExpressionNode *arg){
569    if (arguments)
570        arguments->set_link(arg);
571    else
572        set_args(arg);
573}
574
575CommaExprNode::CommaExprNode(): CompositeExprNode(new OperatorNode(OperatorNode::Comma)) {}
576
577CommaExprNode::CommaExprNode(ExpressionNode *exp) : CompositeExprNode( new OperatorNode(OperatorNode::Comma), exp ) {
578}
579
580CommaExprNode::CommaExprNode(ExpressionNode *exp1, ExpressionNode *exp2) : CompositeExprNode(new OperatorNode(OperatorNode::Comma), exp1, exp2) {
581}
582
583CommaExprNode *CommaExprNode::add_to_list(ExpressionNode *exp){
584    add_arg(exp);
585
586    return this;
587}
588
589CommaExprNode::CommaExprNode( const CommaExprNode &other ) : CompositeExprNode( other ) {
590}
591
592ValofExprNode::ValofExprNode(StatementNode *s): body(s) {}
593
594ValofExprNode::ValofExprNode( const ValofExprNode &other ) : ExpressionNode( other ), body( maybeClone( body ) ) {
595}
596
597ValofExprNode::~ValofExprNode() {
598    delete body;
599}
600
601void ValofExprNode::print( std::ostream &os, int indent ) const {
602    printDesignation(os);
603    os << string(indent, ' ') << "Valof Expression:" << std::endl;
604    get_body()->print(os, indent + 4);
605}
606
607void ValofExprNode::printOneLine( std::ostream &, int indent ) const {
608    assert( false );
609}
610
611Expression *ValofExprNode::build() const {
612    return new UntypedValofExpr ( get_body()->build(), maybeBuild< Expression >( get_argName() ) );
613}
614
615ForCtlExprNode::ForCtlExprNode(ParseNode *init_, ExpressionNode *cond, ExpressionNode *incr) throw (SemanticError) : condition(cond), change(incr) {
616    if ( init_ == 0 )
617        init = 0;
618    else {
619        DeclarationNode *decl;
620        ExpressionNode *exp;
621
622        if ((decl = dynamic_cast<DeclarationNode *>(init_)) != 0)
623            init = new StatementNode(decl);
624        else if ((exp = dynamic_cast<ExpressionNode *>(init_)) != 0)
625            init = new StatementNode(StatementNode::Exp, exp);
626        else
627            throw SemanticError("Error in for control expression");
628    }
629}
630
631ForCtlExprNode::ForCtlExprNode( const ForCtlExprNode &other )
632    : ExpressionNode( other ), init( maybeClone( other.init ) ), condition( maybeClone( other.condition ) ), change( maybeClone( other.change ) ) {
633}
634
635ForCtlExprNode::~ForCtlExprNode(){
636    delete init;
637    delete condition;
638    delete change;
639}
640
641Expression *ForCtlExprNode::build() const {
642    // this shouldn't be used!
643    assert( false );
644    return 0;
645}
646
647void ForCtlExprNode::print( std::ostream &os, int indent ) const{
648    os << string(indent,' ') << "For Control Expression -- : " << endl;
649
650    os << "\r" << string(indent + 2,' ') << "initialization: ";
651    if (init != 0)
652        init->print(os, indent + 4);
653
654    os << "\n\r" << string(indent + 2,' ') << "condition: ";
655    if (condition != 0)
656        condition->print(os, indent + 4);
657    os << "\n\r" << string(indent + 2,' ') << "increment: ";
658    if (change != 0)
659        change->print(os, indent + 4);
660}
661
662void ForCtlExprNode::printOneLine( std::ostream &, int indent ) const {
663    assert( false );
664}
665
666TypeValueNode::TypeValueNode(DeclarationNode *decl)
667    : decl( decl ) {
668}
669
670TypeValueNode::TypeValueNode( const TypeValueNode &other )
671    : ExpressionNode( other ), decl( maybeClone( other.decl ) ) {
672}
673
674Expression *TypeValueNode::build() const {
675    return new TypeExpr( decl->buildType() );
676}
677
678void TypeValueNode::print(std::ostream &os, int indent) const {
679    os << std::string( indent, ' ' ) << "Type:";
680    get_decl()->print(os, indent + 2);
681}
682
683void TypeValueNode::printOneLine(std::ostream &os, int indent) const {
684    os << "Type:";
685    get_decl()->print(os, indent + 2);
686}
687
688ExpressionNode *flattenCommas( ExpressionNode *list ) {
689    if ( CompositeExprNode *composite = dynamic_cast< CompositeExprNode * >( list ) )
690        {
691            OperatorNode *op;
692            if ( (op = dynamic_cast< OperatorNode * >( composite->get_function() )) && (op->get_type() == OperatorNode::Comma) )
693                {
694                    if ( ExpressionNode *next = dynamic_cast< ExpressionNode * >( list->get_link() ) )
695                        composite->add_arg( next );
696                    return flattenCommas( composite->get_args() );
697                }
698        }
699
700    if ( ExpressionNode *next = dynamic_cast< ExpressionNode * >( list->get_link() ) )
701        list->set_next( flattenCommas( next ) );
702
703    return list;
704}
705
706ExpressionNode *tupleContents( ExpressionNode *tuple ) {
707    if ( CompositeExprNode *composite = dynamic_cast< CompositeExprNode * >( tuple ) ) {
708        OperatorNode *op = 0;
709        if ( (op = dynamic_cast< OperatorNode * >( composite->get_function() )) && (op->get_type() == OperatorNode::TupleC) )
710            return composite->get_args();
711    }
712    return tuple;
713}
Note: See TracBrowser for help on using the repository browser.