source: src/Parser/ExpressionNode.cc @ a65d92e

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 a65d92e was 44b5ca0, checked in by Peter A. Buhr <pabuhr@…>, 9 years ago

remove all carriage returns from printing, work on regression testing

  • 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 : Fri Jun  5 07:44:47 2015
13// Update Count     : 10
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          case Integer:
183                os << value ;
184                break;
185          case Float:
186                os << value ;
187                break;
188          case Character:
189                os << "'" << value << "'";
190                break;
191          case String:
192                os << '"' << value << '"';
193                break;
194        } // switch
195
196        os << ' ';
197}
198
199void ConstantNode::print( std::ostream &os, int indent ) const {
200        printOneLine( os, indent );
201        os << endl;
202}
203
204Expression *ConstantNode::build() const {
205        ::Type::Qualifiers q;
206        BasicType *bt;
207
208        switch ( get_type()) {
209          case Integer:
210                /* Cfr. standard 6.4.4.1 */
211                //bt.set_kind( BasicType::SignedInt );
212                bt = new BasicType( q, BasicType::SignedInt );
213                break;
214          case Float:
215                // floating-point constants are type double
216                bt = new BasicType( q, BasicType::Double );
217                break;
218          case Character:
219                bt = new BasicType( q, BasicType::Char );
220                break;
221          case String:
222                // string should probably be a primitive type
223                ArrayType *at;
224                std::string value = get_value();
225                at = new ArrayType( q, new BasicType( q, BasicType::Char ),
226                                                        new ConstantExpr( Constant( new BasicType( q, BasicType::SignedInt ),
227                                                                                                                toString( value.size() - 1 ) ) ),  // account for '\0'
228                                                        false, false );
229                return new ConstantExpr( Constant( at, value ), maybeBuild< Expression >( get_argName() ) );
230        }
231        return new ConstantExpr(  Constant( bt, get_value()),  maybeBuild< Expression >( get_argName() ) );
232}
233
234VarRefNode::VarRefNode() : isLabel( false ) {}
235
236VarRefNode::VarRefNode( string *name_, bool labelp ) : ExpressionNode( name_), isLabel( labelp ) {}
237
238VarRefNode::VarRefNode( const VarRefNode &other ) : ExpressionNode( other ), isLabel( other.isLabel ) {
239}
240
241Expression *VarRefNode::build() const {
242        return new NameExpr( get_name(), maybeBuild< Expression >( get_argName() ) );
243}
244
245void VarRefNode::printOneLine( std::ostream &os, int indent ) const {
246        printDesignation( os );
247        os << get_name() << ' ';
248}
249
250void VarRefNode::print( std::ostream &os, int indent ) const {
251        printDesignation( os );
252        os << string( indent, ' ' ) << "Referencing: ";
253        os << "Variable: " << get_name();
254        os << endl;
255}
256
257OperatorNode::OperatorNode( Type t ) : type( t ) {}
258
259OperatorNode::OperatorNode( const OperatorNode &other ) : ExpressionNode( other ), type( other.type ) {
260}
261
262OperatorNode::~OperatorNode() {}
263
264OperatorNode::Type OperatorNode::get_type( void ) const{
265        return type;
266}
267
268void OperatorNode::printOneLine( std::ostream &os, int indent ) const {
269        printDesignation( os );
270        os << OpName[ type ] << ' ';
271}
272
273void OperatorNode::print( std::ostream &os, int indent ) const{
274        printDesignation( os );
275        os << string( indent, ' ' ) << "Operator: " << OpName[type] << endl;
276        return;
277}
278
279std::string OperatorNode::get_typename( void ) const{
280        return string( OpName[ type ]);
281}
282
283const char *OperatorNode::OpName[] = {
284        "TupleC",  "Comma", "TupleFieldSel",// "TuplePFieldSel", //n-adic
285        // triadic
286        "Cond",   "NCond",
287        // diadic
288        "SizeOf",      "AlignOf", "Attr", "CompLit", "Plus",    "Minus",   "Mul",     "Div",     "Mod",      "Or",
289        "And",       "BitOr",   "BitAnd",  "Xor",     "Cast",    "LShift",  "RShift",  "LThan",   "GThan",
290        "LEThan",    "GEThan", "Eq",      "Neq",     "Assign",  "MulAssn", "DivAssn", "ModAssn", "PlusAssn",
291        "MinusAssn", "LSAssn", "RSAssn",  "AndAssn", "ERAssn",  "OrAssn",  "Index",   "FieldSel","PFieldSel",
292        "Range",
293        // monadic
294        "UnPlus", "UnMinus", "AddressOf", "PointTo", "Neg", "BitNeg", "Incr", "IncrPost", "Decr", "DecrPost", "LabelAddress"
295};
296
297CompositeExprNode::CompositeExprNode( void ) : ExpressionNode(), function( 0 ), arguments( 0 ) {
298}
299
300CompositeExprNode::CompositeExprNode( string *name_) : ExpressionNode( name_), function( 0 ), arguments( 0 ) {
301}
302
303CompositeExprNode::CompositeExprNode( ExpressionNode *f, ExpressionNode *args ):
304        function( f ), arguments( args ) {
305}
306
307CompositeExprNode::CompositeExprNode( ExpressionNode *f, ExpressionNode *arg1, ExpressionNode *arg2):
308        function( f ), arguments( arg1) {
309        arguments->set_link( arg2);
310}
311
312CompositeExprNode::CompositeExprNode( const CompositeExprNode &other ) : ExpressionNode( other ), function( maybeClone( other.function ) ) {
313        ParseNode *cur = other.arguments;
314        while ( cur ) {
315                if ( arguments ) {
316                        arguments->set_link( cur->clone() );
317                } else {
318                        arguments = ( ExpressionNode*)cur->clone();
319                } // if
320                cur = cur->get_link();
321        }
322}
323
324CompositeExprNode::~CompositeExprNode() {
325        delete function;
326        delete arguments;
327}
328
329// the names that users use to define operator functions
330static const char *opFuncName[] = {
331        "",  "", "",
332        "",   "",
333        // diadic
334        "",   "", "", "", "?+?",    "?-?",   "?*?",     "?/?",     "?%?",     "",       "",
335        "?|?",  "?&?",  "?^?",     "",    "?<<?",  "?>>?",  "?<?",   "?>?",    "?<=?",
336        "?>=?", "?==?",      "?!=?",     "?=?",  "?*=?", "?/=?", "?%=?", "?+=?", "?-=?",
337        "?<<=?", "?>>=?",  "?&=?", "?^=?",  "?|=?",  "?[?]",   "","","Range",
338        // monadic
339        "+?", "-?", "", "*?", "!?", "~?", "++?", "?++", "--?", "?--", "LabAddress"
340};
341
342#include "utility.h"
343
344Expression *CompositeExprNode::build() const {
345        OperatorNode *op;
346        std::list<Expression *> args;
347
348        buildList( get_args(), args );
349
350        if ( ! ( op = dynamic_cast<OperatorNode *>( function )) ) {
351                // a function as opposed to an operator
352                return new UntypedExpr( function->build(), args, maybeBuild< Expression >( get_argName() ));
353        } else {
354                switch ( op->get_type()) {
355                  case OperatorNode::Incr:
356                  case OperatorNode::Decr:
357                  case OperatorNode::IncrPost:
358                  case OperatorNode::DecrPost:
359                  case OperatorNode::Assign:
360                  case OperatorNode::MulAssn:
361                  case OperatorNode::DivAssn:
362                  case OperatorNode::ModAssn:
363                  case OperatorNode::PlusAssn:
364                  case OperatorNode::MinusAssn:
365                  case OperatorNode::LSAssn:
366                  case OperatorNode::RSAssn:
367                  case OperatorNode::AndAssn:
368                  case OperatorNode::ERAssn:
369                  case OperatorNode::OrAssn:
370                        // the rewrite rules for these expressions specify that the first argument has its address taken
371                        assert( ! args.empty() );
372                        args.front() = new AddressExpr( args.front() );
373                        break;
374                  default:
375                        /* do nothing */
376                        ;
377                }
378
379                switch ( op->get_type() ) {
380                  case OperatorNode::Incr:
381                  case OperatorNode::Decr:
382                  case OperatorNode::IncrPost:
383                  case OperatorNode::DecrPost:
384                  case OperatorNode::Assign:
385                  case OperatorNode::MulAssn:
386                  case OperatorNode::DivAssn:
387                  case OperatorNode::ModAssn:
388                  case OperatorNode::PlusAssn:
389                  case OperatorNode::MinusAssn:
390                  case OperatorNode::LSAssn:
391                  case OperatorNode::RSAssn:
392                  case OperatorNode::AndAssn:
393                  case OperatorNode::ERAssn:
394                  case OperatorNode::OrAssn:
395                  case OperatorNode::Plus:
396                  case OperatorNode::Minus:
397                  case OperatorNode::Mul:
398                  case OperatorNode::Div:
399                  case OperatorNode::Mod:
400                  case OperatorNode::BitOr:
401                  case OperatorNode::BitAnd:
402                  case OperatorNode::Xor:
403                  case OperatorNode::LShift:
404                  case OperatorNode::RShift:
405                  case OperatorNode::LThan:
406                  case OperatorNode::GThan:
407                  case OperatorNode::LEThan:
408                  case OperatorNode::GEThan:
409                  case OperatorNode::Eq:
410                  case OperatorNode::Neq:
411                  case OperatorNode::Index:
412                  case OperatorNode::Range:
413                  case OperatorNode::UnPlus:
414                  case OperatorNode::UnMinus:
415                  case OperatorNode::PointTo:
416                  case OperatorNode::Neg:
417                  case OperatorNode::BitNeg:
418                  case OperatorNode::LabelAddress:
419                        return new UntypedExpr( new NameExpr( opFuncName[ op->get_type() ] ), args );
420                  case OperatorNode::AddressOf:
421                        assert( args.size() == 1 );
422                        assert( args.front() );
423
424                        return new AddressExpr( args.front() );
425                  case OperatorNode::Cast:
426                        {
427                                TypeValueNode * arg = dynamic_cast<TypeValueNode *>( get_args());
428                                assert( arg );
429
430                                DeclarationNode *decl_node = arg->get_decl();
431                                ExpressionNode *expr_node = dynamic_cast<ExpressionNode *>( arg->get_link());
432
433                                Type *targetType = decl_node->buildType();
434                                if ( dynamic_cast< VoidType* >( targetType ) ) {
435                                        delete targetType;
436                                        return new CastExpr( expr_node->build(), maybeBuild< Expression >( get_argName() ) );
437                                } else {
438                                        return new CastExpr( expr_node->build(),targetType, maybeBuild< Expression >( get_argName() ) );
439                                } // if
440                        }
441                  case OperatorNode::FieldSel:
442                        {
443                                assert( args.size() == 2 );
444
445                                NameExpr *member = dynamic_cast<NameExpr *>( args.back());
446                                // TupleExpr *memberTup = dynamic_cast<TupleExpr *>( args.back());
447
448                                if ( member != 0 ) {
449                                        UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), args.front());
450                                        delete member;
451                                        return ret;
452                                        /* else if ( memberTup != 0 )
453                                           {
454                                           UntypedMemberExpr *ret = new UntypedMemberExpr( memberTup->get_name(), args.front());
455                                           delete member;
456                                           return ret;
457                                           } */
458                                } else
459                                        assert( false );
460                        }
461                  case OperatorNode::PFieldSel:
462                        {
463                                assert( args.size() == 2 );
464
465                                NameExpr *member = dynamic_cast<NameExpr *>( args.back());  // modify for Tuples   xxx
466                                assert( member != 0 );
467
468                                UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
469                                deref->get_args().push_back( args.front() );
470
471                                UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), deref );
472                                delete member;
473                                return ret;
474                        }
475                  case OperatorNode::AlignOf:
476                  case OperatorNode::SizeOf:
477                        {
478///     bool isSizeOf = ( op->get_type() == OperatorNode::SizeOf );
479
480                                if ( TypeValueNode * arg = dynamic_cast<TypeValueNode *>( get_args()) ) {
481                                        return new SizeofExpr( arg->get_decl()->buildType());
482                                } else {
483                                        return new SizeofExpr( args.front());
484                                } // if
485                        }
486                  case OperatorNode::Attr:
487                        {
488                                VarRefNode *var = dynamic_cast<VarRefNode *>( get_args());
489                                assert( var );
490                                if ( ! get_args()->get_link() ) {
491                                        return new AttrExpr( var->build(), ( Expression*)0);
492                                } else if ( TypeValueNode * arg = dynamic_cast<TypeValueNode *>( get_args()->get_link()) ) {
493                                        return new AttrExpr( var->build(), arg->get_decl()->buildType());
494                                } else {
495                                        return new AttrExpr( var->build(), args.back());
496                                } // if
497                        }
498                  case OperatorNode::CompLit:
499                        throw UnimplementedError( "C99 compound literals" );
500                        // the short-circuited operators
501                  case OperatorNode::Or:
502                  case OperatorNode::And:
503                        assert( args.size() == 2);
504                        return new LogicalExpr( notZeroExpr( args.front() ), notZeroExpr( args.back() ), ( op->get_type() == OperatorNode::And ) );
505                  case OperatorNode::Cond:
506                        {
507                                assert( args.size() == 3);
508                                std::list< Expression* >::const_iterator i = args.begin();
509                                Expression *arg1 = notZeroExpr( *i++ );
510                                Expression *arg2 = *i++;
511                                Expression *arg3 = *i++;
512                                return new ConditionalExpr( arg1, arg2, arg3 );
513                        }
514                  case OperatorNode::NCond:
515                        throw UnimplementedError( "GNU 2-argument conditional expression" );
516                  case OperatorNode::Comma:
517                        {
518                                assert( args.size() == 2);
519                                std::list< Expression* >::const_iterator i = args.begin();
520                                Expression *ret = *i++;
521                                while ( i != args.end() ) {
522                                        ret = new CommaExpr( ret, *i++ );
523                                }
524                                return ret;
525                        }
526                        // Tuples
527                  case OperatorNode::TupleC:
528                        {
529                                TupleExpr *ret = new TupleExpr();
530                                std::copy( args.begin(), args.end(), back_inserter( ret->get_exprs() ) );
531                                return ret;
532                        }
533                  default:
534                        // shouldn't happen
535                        return 0;
536                }
537        }
538}
539
540void CompositeExprNode::printOneLine( std::ostream &os, int indent ) const {
541        printDesignation( os );
542        os << "( ";
543        function->printOneLine( os, indent );
544        for ( ExpressionNode *cur = arguments; cur != 0; cur = dynamic_cast< ExpressionNode* >( cur->get_link() ) ) {
545                cur->printOneLine( os, indent );
546        }
547        os << ") ";
548}
549
550void CompositeExprNode::print( std::ostream &os, int indent ) const {
551        printDesignation( os );
552        os << string( indent, ' ' ) << "Application of: " << endl;
553        function->print( os, indent + ParseNode::indent_by );
554
555        os << string( indent, ' ' ) ;
556        if ( arguments ) {
557                os << "... on arguments: " << endl;
558                arguments->printList( os, indent + ParseNode::indent_by );
559        } else
560                os << "... on no arguments: " << endl;
561}
562
563void CompositeExprNode::set_function( ExpressionNode *f ) {
564        function = f;
565}
566
567void CompositeExprNode::set_args( ExpressionNode *args ) {
568        arguments = args;
569}
570
571ExpressionNode *CompositeExprNode::get_function( void ) const {
572        return function;
573}
574
575ExpressionNode *CompositeExprNode::get_args( void ) const {
576        return arguments;
577}
578
579void CompositeExprNode::add_arg( ExpressionNode *arg ) {
580        if ( arguments )
581                arguments->set_link( arg );
582        else
583                set_args( arg );
584}
585
586CommaExprNode::CommaExprNode(): CompositeExprNode( new OperatorNode( OperatorNode::Comma )) {}
587
588CommaExprNode::CommaExprNode( ExpressionNode *exp ) : CompositeExprNode( new OperatorNode( OperatorNode::Comma ), exp ) {
589}
590
591CommaExprNode::CommaExprNode( ExpressionNode *exp1, ExpressionNode *exp2) : CompositeExprNode( new OperatorNode( OperatorNode::Comma ), exp1, exp2) {
592}
593
594CommaExprNode *CommaExprNode::add_to_list( ExpressionNode *exp ) {
595        add_arg( exp );
596
597        return this;
598}
599
600CommaExprNode::CommaExprNode( const CommaExprNode &other ) : CompositeExprNode( other ) {
601}
602
603ValofExprNode::ValofExprNode( StatementNode *s ): body( s ) {}
604
605ValofExprNode::ValofExprNode( const ValofExprNode &other ) : ExpressionNode( other ), body( maybeClone( body ) ) {
606}
607
608ValofExprNode::~ValofExprNode() {
609        delete body;
610}
611
612void ValofExprNode::print( std::ostream &os, int indent ) const {
613        printDesignation( os );
614        os << string( indent, ' ') << "Valof Expression:" << std::endl;
615        get_body()->print( os, indent + 4);
616}
617
618void ValofExprNode::printOneLine( std::ostream &, int indent ) const {
619        assert( false );
620}
621
622Expression *ValofExprNode::build() const {
623        return new UntypedValofExpr ( get_body()->build(), maybeBuild< Expression >( get_argName() ) );
624}
625
626ForCtlExprNode::ForCtlExprNode( ParseNode *init_, ExpressionNode *cond, ExpressionNode *incr ) throw ( SemanticError ) : condition( cond ), change( incr ) {
627        if ( init_ == 0 )
628                init = 0;
629        else {
630                DeclarationNode *decl;
631                ExpressionNode *exp;
632
633                if (( decl = dynamic_cast<DeclarationNode *>(init_) ) != 0)
634                        init = new StatementNode( decl );
635                else if (( exp = dynamic_cast<ExpressionNode *>( init_)) != 0)
636                        init = new StatementNode( StatementNode::Exp, exp );
637                else
638                        throw SemanticError("Error in for control expression");
639        }
640}
641
642ForCtlExprNode::ForCtlExprNode( const ForCtlExprNode &other )
643        : ExpressionNode( other ), init( maybeClone( other.init ) ), condition( maybeClone( other.condition ) ), change( maybeClone( other.change ) ) {
644}
645
646ForCtlExprNode::~ForCtlExprNode() {
647        delete init;
648        delete condition;
649        delete change;
650}
651
652Expression *ForCtlExprNode::build() const {
653        // this shouldn't be used!
654        assert( false );
655        return 0;
656}
657
658void ForCtlExprNode::print( std::ostream &os, int indent ) const{
659        os << string( indent,' ') << "For Control Expression -- :" << endl;
660
661        os << string( indent + 2,' ' ) << "initialization:" << endl;
662        if ( init != 0 )
663                init->printList( os, indent + 4 );
664
665        os << string( indent + 2, ' ' ) << "condition: " << endl;
666        if ( condition != 0 )
667                condition->print( os, indent + 4 );
668        os << string( indent + 2,' ' ) << "increment: " << endl;
669        if ( change != 0 )
670                change->print( os, indent + 4 );
671}
672
673void ForCtlExprNode::printOneLine( std::ostream &, int indent ) const {
674        assert( false );
675}
676
677TypeValueNode::TypeValueNode( DeclarationNode *decl )
678        : decl( decl ) {
679}
680
681TypeValueNode::TypeValueNode( const TypeValueNode &other )
682        : ExpressionNode( other ), decl( maybeClone( other.decl ) ) {
683}
684
685Expression *TypeValueNode::build() const {
686        return new TypeExpr( decl->buildType() );
687}
688
689void TypeValueNode::print( std::ostream &os, int indent ) const {
690        os << std::string( indent, ' ' ) << "Type:";
691        get_decl()->print( os, indent + 2);
692}
693
694void TypeValueNode::printOneLine( std::ostream &os, int indent ) const {
695        os << "Type:";
696        get_decl()->print( os, indent + 2);
697}
698
699ExpressionNode *flattenCommas( ExpressionNode *list ) {
700        if ( CompositeExprNode *composite = dynamic_cast< CompositeExprNode * >( list ) )
701                {
702                        OperatorNode *op;
703                        if ( ( op = dynamic_cast< OperatorNode * >( composite->get_function() )) && ( op->get_type() == OperatorNode::Comma ) )
704                                {
705                                        if ( ExpressionNode *next = dynamic_cast< ExpressionNode * >( list->get_link() ) )
706                                                composite->add_arg( next );
707                                        return flattenCommas( composite->get_args() );
708                                }
709                }
710
711        if ( ExpressionNode *next = dynamic_cast< ExpressionNode * >( list->get_link() ) )
712                list->set_next( flattenCommas( next ) );
713
714        return list;
715}
716
717ExpressionNode *tupleContents( ExpressionNode *tuple ) {
718        if ( CompositeExprNode *composite = dynamic_cast< CompositeExprNode * >( tuple ) ) {
719                OperatorNode *op = 0;
720                if ( ( op = dynamic_cast< OperatorNode * >( composite->get_function() )) && ( op->get_type() == OperatorNode::TupleC ) )
721                        return composite->get_args();
722        }
723        return tuple;
724}
725
726// Local Variables: //
727// tab-width: 4 //
728// mode: c++ //
729// compile-command: "make install" //
730// End: //
Note: See TracBrowser for help on using the repository browser.