source: translator/Parser/ExpressionNode.cc @ 51b7345

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 51b7345 was 51b7345, checked in by Peter A. Buhr <pabuhr@…>, 10 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.