source: src/Parser/ExpressionNode.cc @ a61fea9a

aaron-thesisarm-ehcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerresolv-newstringwith_gc
Last change on this file since a61fea9a was a61fea9a, checked in by Peter A. Buhr <pabuhr@…>, 7 years ago

enable AM_MAINTAINER_MODE, add operator ?{}, formatting

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