source: translator/Parser.old/ExpressionNode.cc @ 8c17ab0

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

initial commit

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