// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // ExpressionNode.cc -- // // Author : Rodolfo G. Esteves // Created On : Sat May 16 13:17:07 2015 // Last Modified By : Rob Schluntz // Last Modified On : Wed Aug 12 13:51:11 2015 // Update Count : 254 // #include #include #include #include #include #include #include "ParseNode.h" #include "SynTree/Constant.h" #include "SynTree/Expression.h" #include "UnimplementedError.h" #include "parseutility.h" #include "utility.h" using namespace std; ExpressionNode::ExpressionNode() : ParseNode(), argName( 0 ) {} ExpressionNode::ExpressionNode( const string *name ) : ParseNode( name ), argName( 0 ) {} ExpressionNode::ExpressionNode( const ExpressionNode &other ) : ParseNode( other.name ) { if ( other.argName ) { argName = other.argName->clone(); } else { argName = 0; } // if } ExpressionNode * ExpressionNode::set_argName( const std::string *aName ) { argName = new VarRefNode( aName ); return this; } ExpressionNode * ExpressionNode::set_argName( ExpressionNode *aDesignator ) { argName = aDesignator; return this; } void ExpressionNode::printDesignation( std::ostream &os, int indent ) const { if ( argName ) { os << string( indent, ' ' ) << "(designated by: "; argName->printOneLine( os, indent ); os << ")" << std::endl; } // if } //############################################################################## NullExprNode::NullExprNode() {} NullExprNode *NullExprNode::clone() const { return new NullExprNode(); } void NullExprNode::print( std::ostream & os, int indent ) const { printDesignation( os ); os << "null expression"; } void NullExprNode::printOneLine( std::ostream & os, int indent ) const { printDesignation( os ); os << "null"; } Expression *NullExprNode::build() const { return 0; } CommaExprNode *ExpressionNode::add_to_list( ExpressionNode *exp ) { return new CommaExprNode( this, exp ); } //############################################################################## static inline bool checkU( char c ) { return c == 'u' || c == 'U'; } static inline bool checkL( char c ) { return c == 'l' || c == 'L'; } static inline bool checkF( char c ) { return c == 'f' || c == 'F'; } static inline bool checkX( char c ) { return c == 'x' || c == 'X'; } // Difficult to separate extra parts of constants during lexing because actions are not allow in the middle of patterns: // // prefix action constant action suffix // // Alternatively, breaking a pattern using BEGIN does not work if the following pattern can be empty: // // constant BEGIN CONT ... // (...)? BEGIN 0 ... // possible empty suffix // // because the CONT rule is NOT triggered if the pattern is empty. Hence, constants are reparsed here to determine their // type. ConstantNode::ConstantNode( Type t, string *inVal ) : type( t ), value( *inVal ) { // lexing divides constants into 4 kinds switch ( type ) { case Integer: { static const BasicType::Kind kind[2][3] = { { BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt }, { BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt }, }; size_t last = value.length() - 1; // last character of constant unsigned long long v; // converted integral value bool dec = true, Unsigned = false; // decimal, unsigned constant int size; // 0 => int, 1 => long, 2 => long long if ( value[0] == '0' ) { // octal constant ? dec = false; if ( last != 0 && checkX( value[1] ) ) { // hex constant ? sscanf( (char *)value.c_str(), "%llx", &v ); //printf( "%llx %llu\n", v, v ); } else { sscanf( (char *)value.c_str(), "%llo", &v ); //printf( "%llo %llu\n", v, v ); } // if } else { // decimal constant ? sscanf( (char *)value.c_str(), "%llu", &v ); //printf( "%llu %llu\n", v, v ); } // if if ( v <= INT_MAX ) { // signed int size = 0; } else if ( v <= UINT_MAX && ! dec ) { // unsigned int size = 0; Unsigned = true; // unsigned } else if ( v <= LONG_MAX ) { // signed long int size = 1; } else if ( v <= ULONG_MAX && ( ! dec || LONG_MAX == LLONG_MAX ) ) { // signed long int size = 1; Unsigned = true; // unsigned long int } else if ( v <= LLONG_MAX ) { // signed long long int size = 2; } else { // unsigned long long int size = 2; Unsigned = true; // unsigned long long int } // if if ( checkU( value[last] ) ) { // suffix 'u' ? Unsigned = true; if ( last > 0 && checkL( value[ last - 1 ] ) ) { // suffix 'l' ? size = 1; if ( last > 1 && checkL( value[ last - 2 ] ) ) { // suffix 'll' ? size = 2; } // if } // if } else if ( checkL( value[ last ] ) ) { // suffix 'l' ? size = 1; if ( last > 0 && checkL( value[ last - 1 ] ) ) { // suffix 'll' ? size = 2; if ( last > 1 && checkU( value[ last - 2 ] ) ) { // suffix 'u' ? Unsigned = true; } // if } else { if ( last > 0 && checkU( value[ last - 1 ] ) ) { // suffix 'u' ? Unsigned = true; } // if } // if } // if btype = kind[Unsigned][size]; // lookup constant type break; } case Float: { size_t len = value.length() - 1; btype = BasicType::Double; // default if ( checkF( value[len] ) ) { // float ? btype = BasicType::Float; } // if if ( checkL( value[len] ) ) { // long double ? btype = BasicType::LongDouble; } // if break; } case Character: btype = BasicType::Char; // default if ( string( "LUu" ).find( value[0] ) != string::npos ) { // ??? } // if break; case String: // array of char if ( string( "LUu" ).find( value[0] ) != string::npos ) { if ( value[0] == 'u' && value[1] == '8' ) { // ??? } else { // ??? } // if } // if break; } // switch } // ConstantNode::ConstantNode ConstantNode *ConstantNode::appendstr( const std::string *newValue ) { assert( newValue != 0 ); assert( type == String ); // "abc" "def" "ghi" => "abcdefghi", remove new text from quotes and insert before last quote in old string. value.insert( value.length() - 1, newValue->substr( 1, newValue->length() - 2 ) ); delete newValue; // allocated by lexer return this; } void ConstantNode::printOneLine( std::ostream &os, int indent ) const { os << string( indent, ' ' ); printDesignation( os ); switch ( type ) { case Integer: case Float: os << value ; break; case Character: os << "'" << value << "'"; break; case String: os << '"' << value << '"'; break; } // switch os << ' '; } void ConstantNode::print( std::ostream &os, int indent ) const { printOneLine( os, indent ); os << endl; } Expression *ConstantNode::build() const { ::Type::Qualifiers q; // no qualifiers on constants switch ( get_type() ) { case String: { // string should probably be a primitive type ArrayType *at = new ArrayType( q, new BasicType( q, BasicType::Char ), new ConstantExpr( Constant( new BasicType( q, BasicType::UnsignedInt ), toString( value.size()+1-2 ) ) ), // +1 for '\0' and -2 for '"' false, false ); return new ConstantExpr( Constant( at, value ), maybeBuild< Expression >( get_argName() ) ); } default: return new ConstantExpr( Constant( new BasicType( q, btype ), get_value() ), maybeBuild< Expression >( get_argName() ) ); } } //############################################################################## VarRefNode::VarRefNode() : isLabel( false ) {} VarRefNode::VarRefNode( const string *name_, bool labelp ) : ExpressionNode( name_ ), isLabel( labelp ) {} VarRefNode::VarRefNode( const VarRefNode &other ) : ExpressionNode( other ), isLabel( other.isLabel ) { } Expression *VarRefNode::build() const { return new NameExpr( get_name(), maybeBuild< Expression >( get_argName() ) ); } void VarRefNode::printOneLine( std::ostream &os, int indent ) const { printDesignation( os ); os << get_name() << ' '; } void VarRefNode::print( std::ostream &os, int indent ) const { printDesignation( os ); os << string( indent, ' ' ) << "Referencing: "; os << "Variable: " << get_name(); os << endl; } //############################################################################## DesignatorNode::DesignatorNode( ExpressionNode *expr, bool isArrayIndex ) : isArrayIndex( isArrayIndex ) { set_argName( expr ); assert( get_argName() ); if ( ! isArrayIndex ) { if ( VarRefNode * var = dynamic_cast< VarRefNode * >( expr ) ) { stringstream ss( var->get_name() ); double value; if ( ss >> value ) { // this is a floating point constant. It MUST be // ".0" or ".1", otherwise the program is invalid if ( ! (var->get_name() == ".0" || var->get_name() == ".1") ) { throw SemanticError( "invalid designator name: " + var->get_name() ); } // if var->set_name( var->get_name().substr(1) ); } // if } // if } // if } DesignatorNode::DesignatorNode( const DesignatorNode &other ) : ExpressionNode( other ), isArrayIndex( other.isArrayIndex ) { } class DesignatorFixer : public Mutator { public: virtual Expression* mutate( NameExpr *nameExpr ) { if ( nameExpr->get_name() == "0" || nameExpr->get_name() == "1" ) { Constant val( new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nameExpr->get_name() ); delete nameExpr; return new ConstantExpr( val ); } return nameExpr; } }; Expression *DesignatorNode::build() const { Expression * ret = get_argName()->build(); if ( isArrayIndex ) { // need to traverse entire structure and change any instances of 0 or 1 to // ConstantExpr DesignatorFixer fixer; ret = ret->acceptMutator( fixer ); } // if return ret; } void DesignatorNode::printOneLine( std::ostream &os, int indent ) const { if ( get_argName() ) { if ( isArrayIndex ) { os << "["; get_argName()->printOneLine( os, indent ); os << "]"; } else { os << "."; get_argName()->printOneLine( os, indent ); } } // if } void DesignatorNode::print( std::ostream &os, int indent ) const { if ( get_argName() ) { if ( isArrayIndex ) { os << "["; get_argName()->print( os, indent ); os << "]"; } else { os << "."; get_argName()->print( os, indent ); } } // if } //############################################################################## OperatorNode::OperatorNode( Type t ) : type( t ) {} OperatorNode::OperatorNode( const OperatorNode &other ) : ExpressionNode( other ), type( other.type ) { } OperatorNode::~OperatorNode() {} OperatorNode::Type OperatorNode::get_type( void ) const{ return type; } void OperatorNode::printOneLine( std::ostream &os, int indent ) const { printDesignation( os ); os << OpName[ type ] << ' '; } void OperatorNode::print( std::ostream &os, int indent ) const{ printDesignation( os ); os << string( indent, ' ' ) << "Operator: " << OpName[type] << endl; return; } const char *OperatorNode::get_typename( void ) const{ return OpName[ type ]; } const char *OperatorNode::OpName[] = { "TupleC", "Comma", "TupleFieldSel",// "TuplePFieldSel", //n-adic // triadic "Cond", "NCond", // diadic "SizeOf", "AlignOf", "Attr", "CompLit", "Plus", "Minus", "Mul", "Div", "Mod", "Or", "And", "BitOr", "BitAnd", "Xor", "Cast", "LShift", "RShift", "LThan", "GThan", "LEThan", "GEThan", "Eq", "Neq", "Assign", "MulAssn", "DivAssn", "ModAssn", "PlusAssn", "MinusAssn", "LSAssn", "RSAssn", "AndAssn", "ERAssn", "OrAssn", "Index", "FieldSel","PFieldSel", "Range", // monadic "UnPlus", "UnMinus", "AddressOf", "PointTo", "Neg", "BitNeg", "Incr", "IncrPost", "Decr", "DecrPost", "LabelAddress" }; //############################################################################## CompositeExprNode::CompositeExprNode() : ExpressionNode(), function( 0 ), arguments( 0 ) { } CompositeExprNode::CompositeExprNode( const string *name_ ) : ExpressionNode( name_ ), function( 0 ), arguments( 0 ) { } CompositeExprNode::CompositeExprNode( ExpressionNode *f, ExpressionNode *args ): function( f ), arguments( args ) { } CompositeExprNode::CompositeExprNode( ExpressionNode *f, ExpressionNode *arg1, ExpressionNode *arg2): function( f ), arguments( arg1) { arguments->set_link( arg2); } CompositeExprNode::CompositeExprNode( const CompositeExprNode &other ) : ExpressionNode( other ), function( maybeClone( other.function ) ) { ParseNode *cur = other.arguments; while ( cur ) { if ( arguments ) { arguments->set_link( cur->clone() ); } else { arguments = ( ExpressionNode*)cur->clone(); } // if cur = cur->get_link(); } } CompositeExprNode::~CompositeExprNode() { delete function; delete arguments; } // the names that users use to define operator functions static const char *opFuncName[] = { "", "", "", "", "", //diadic "", "", "", "", "?+?", "?-?", "?*?", "?/?", "?%?", "", "", "?|?", "?&?", "?^?", "", "?<>?", "??", "?<=?", "?>=?", "?==?", "?!=?", "?=?", "?*=?", "?/=?", "?%=?", "?+=?", "?-=?", "?<<=?", "?>>=?", "?&=?", "?^=?", "?|=?", "?[?]", "", "", "Range", //monadic "+?", "-?", "", "*?", "!?", "~?", "++?", "?++", "--?", "?--", "&&" }; #include "utility.h" Expression *CompositeExprNode::build() const { OperatorNode *op; std::list args; buildList( get_args(), args ); if ( ! ( op = dynamic_cast( function ) ) ) { // function as opposed to operator return new UntypedExpr( function->build(), args, maybeBuild< Expression >( get_argName() )); } // if switch ( op->get_type()) { case OperatorNode::Incr: case OperatorNode::Decr: case OperatorNode::IncrPost: case OperatorNode::DecrPost: case OperatorNode::Assign: case OperatorNode::MulAssn: case OperatorNode::DivAssn: case OperatorNode::ModAssn: case OperatorNode::PlusAssn: case OperatorNode::MinusAssn: case OperatorNode::LSAssn: case OperatorNode::RSAssn: case OperatorNode::AndAssn: case OperatorNode::ERAssn: case OperatorNode::OrAssn: // the rewrite rules for these expressions specify that the first argument has its address taken assert( ! args.empty() ); args.front() = new AddressExpr( args.front() ); break; default: /* do nothing */ ; } switch ( op->get_type() ) { case OperatorNode::Incr: case OperatorNode::Decr: case OperatorNode::IncrPost: case OperatorNode::DecrPost: case OperatorNode::Assign: case OperatorNode::MulAssn: case OperatorNode::DivAssn: case OperatorNode::ModAssn: case OperatorNode::PlusAssn: case OperatorNode::MinusAssn: case OperatorNode::LSAssn: case OperatorNode::RSAssn: case OperatorNode::AndAssn: case OperatorNode::ERAssn: case OperatorNode::OrAssn: case OperatorNode::Plus: case OperatorNode::Minus: case OperatorNode::Mul: case OperatorNode::Div: case OperatorNode::Mod: case OperatorNode::BitOr: case OperatorNode::BitAnd: case OperatorNode::Xor: case OperatorNode::LShift: case OperatorNode::RShift: case OperatorNode::LThan: case OperatorNode::GThan: case OperatorNode::LEThan: case OperatorNode::GEThan: case OperatorNode::Eq: case OperatorNode::Neq: case OperatorNode::Index: case OperatorNode::Range: case OperatorNode::UnPlus: case OperatorNode::UnMinus: case OperatorNode::PointTo: case OperatorNode::Neg: case OperatorNode::BitNeg: case OperatorNode::LabelAddress: return new UntypedExpr( new NameExpr( opFuncName[ op->get_type() ] ), args ); case OperatorNode::AddressOf: assert( args.size() == 1 ); assert( args.front() ); return new AddressExpr( args.front() ); case OperatorNode::Cast: { TypeValueNode * arg = dynamic_cast( get_args()); assert( arg ); DeclarationNode *decl_node = arg->get_decl(); ExpressionNode *expr_node = dynamic_cast( arg->get_link()); Type *targetType = decl_node->buildType(); if ( dynamic_cast< VoidType* >( targetType ) ) { delete targetType; return new CastExpr( expr_node->build(), maybeBuild< Expression >( get_argName() ) ); } else { return new CastExpr( expr_node->build(),targetType, maybeBuild< Expression >( get_argName() ) ); } // if } case OperatorNode::FieldSel: { assert( args.size() == 2 ); NameExpr *member = dynamic_cast( args.back()); // TupleExpr *memberTup = dynamic_cast( args.back()); if ( member != 0 ) { UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), args.front()); delete member; return ret; /* else if ( memberTup != 0 ) { UntypedMemberExpr *ret = new UntypedMemberExpr( memberTup->get_name(), args.front()); delete member; return ret; } */ } else assert( false ); } case OperatorNode::PFieldSel: { assert( args.size() == 2 ); NameExpr *member = dynamic_cast( args.back()); // modify for Tuples xxx assert( member != 0 ); UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); deref->get_args().push_back( args.front() ); UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), deref ); delete member; return ret; } case OperatorNode::AlignOf: case OperatorNode::SizeOf: { /// bool isSizeOf = ( op->get_type() == OperatorNode::SizeOf ); if ( TypeValueNode * arg = dynamic_cast( get_args()) ) { return new SizeofExpr( arg->get_decl()->buildType()); } else { return new SizeofExpr( args.front()); } // if } case OperatorNode::Attr: { VarRefNode *var = dynamic_cast( get_args()); assert( var ); if ( ! get_args()->get_link() ) { return new AttrExpr( var->build(), ( Expression*)0); } else if ( TypeValueNode * arg = dynamic_cast( get_args()->get_link()) ) { return new AttrExpr( var->build(), arg->get_decl()->buildType()); } else { return new AttrExpr( var->build(), args.back()); } // if } case OperatorNode::CompLit: throw UnimplementedError( "C99 compound literals" ); // the short-circuited operators case OperatorNode::Or: case OperatorNode::And: assert( args.size() == 2); return new LogicalExpr( notZeroExpr( args.front() ), notZeroExpr( args.back() ), ( op->get_type() == OperatorNode::And ) ); case OperatorNode::Cond: { assert( args.size() == 3); std::list< Expression * >::const_iterator i = args.begin(); Expression *arg1 = notZeroExpr( *i++ ); Expression *arg2 = *i++; Expression *arg3 = *i++; return new ConditionalExpr( arg1, arg2, arg3 ); } case OperatorNode::NCond: throw UnimplementedError( "GNU 2-argument conditional expression" ); case OperatorNode::Comma: { assert( args.size() == 2); std::list< Expression * >::const_iterator i = args.begin(); Expression *ret = *i++; while ( i != args.end() ) { ret = new CommaExpr( ret, *i++ ); } return ret; } // Tuples case OperatorNode::TupleC: { TupleExpr *ret = new TupleExpr(); std::copy( args.begin(), args.end(), back_inserter( ret->get_exprs() ) ); return ret; } default: // shouldn't happen return 0; } // switch } void CompositeExprNode::printOneLine( std::ostream &os, int indent ) const { printDesignation( os ); os << "( "; function->printOneLine( os, indent ); for ( ExpressionNode *cur = arguments; cur != 0; cur = dynamic_cast< ExpressionNode* >( cur->get_link() ) ) { cur->printOneLine( os, indent ); } os << ") "; } void CompositeExprNode::print( std::ostream &os, int indent ) const { printDesignation( os ); os << string( indent, ' ' ) << "Application of: " << endl; function->print( os, indent + ParseNode::indent_by ); os << string( indent, ' ' ) ; if ( arguments ) { os << "... on arguments: " << endl; arguments->printList( os, indent + ParseNode::indent_by ); } else os << "... on no arguments: " << endl; } void CompositeExprNode::set_function( ExpressionNode *f ) { function = f; } void CompositeExprNode::set_args( ExpressionNode *args ) { arguments = args; } ExpressionNode *CompositeExprNode::get_function( void ) const { return function; } ExpressionNode *CompositeExprNode::get_args( void ) const { return arguments; } void CompositeExprNode::add_arg( ExpressionNode *arg ) { if ( arguments ) arguments->set_link( arg ); else set_args( arg ); } //############################################################################## Expression *AsmExprNode::build() const { return new AsmExpr( maybeBuild< Expression >( inout ), (ConstantExpr *)constraint->build(), operand->build() ); } void AsmExprNode::print( std::ostream &os, int indent ) const { os << string( indent, ' ' ) << "Assembler Expression:" << endl; if ( inout ) { os << string( indent, ' ' ) << "inout: " << std::endl; inout->print( os, indent + 2 ); } // if if ( constraint ) { os << string( indent, ' ' ) << "constraint: " << std::endl; constraint->print( os, indent + 2 ); } // if if ( operand ) { os << string( indent, ' ' ) << "operand: " << std::endl; operand->print( os, indent + 2 ); } // if } void AsmExprNode::printOneLine( std::ostream &os, int indent ) const { printDesignation( os ); os << "( "; if ( inout ) inout->printOneLine( os, indent + 2 ); os << ", "; if ( constraint ) constraint->printOneLine( os, indent + 2 ); os << ", "; if ( operand ) operand->printOneLine( os, indent + 2 ); os << ") "; } //############################################################################## void LabelNode::print( std::ostream &os, int indent ) const {} void LabelNode::printOneLine( std::ostream &os, int indent ) const {} //############################################################################## CommaExprNode::CommaExprNode(): CompositeExprNode( new OperatorNode( OperatorNode::Comma )) {} CommaExprNode::CommaExprNode( ExpressionNode *exp ) : CompositeExprNode( new OperatorNode( OperatorNode::Comma ), exp ) { } CommaExprNode::CommaExprNode( ExpressionNode *exp1, ExpressionNode *exp2) : CompositeExprNode( new OperatorNode( OperatorNode::Comma ), exp1, exp2) { } CommaExprNode *CommaExprNode::add_to_list( ExpressionNode *exp ) { add_arg( exp ); return this; } CommaExprNode::CommaExprNode( const CommaExprNode &other ) : CompositeExprNode( other ) { } //############################################################################## ValofExprNode::ValofExprNode( StatementNode *s ): body( s ) {} ValofExprNode::ValofExprNode( const ValofExprNode &other ) : ExpressionNode( other ), body( maybeClone( body ) ) { } ValofExprNode::~ValofExprNode() { delete body; } void ValofExprNode::print( std::ostream &os, int indent ) const { printDesignation( os ); os << string( indent, ' ' ) << "Valof Expression:" << std::endl; get_body()->print( os, indent + 4); } void ValofExprNode::printOneLine( std::ostream &, int indent ) const { assert( false ); } Expression *ValofExprNode::build() const { return new UntypedValofExpr ( get_body()->build(), maybeBuild< Expression >( get_argName() ) ); } //############################################################################## ForCtlExprNode::ForCtlExprNode( ParseNode *init_, ExpressionNode *cond, ExpressionNode *incr ) throw ( SemanticError ) : condition( cond ), change( incr ) { if ( init_ == 0 ) init = 0; else { DeclarationNode *decl; ExpressionNode *exp; if (( decl = dynamic_cast(init_) ) != 0) init = new StatementNode( decl ); else if (( exp = dynamic_cast( init_)) != 0) init = new StatementNode( StatementNode::Exp, exp ); else throw SemanticError("Error in for control expression"); } } ForCtlExprNode::ForCtlExprNode( const ForCtlExprNode &other ) : ExpressionNode( other ), init( maybeClone( other.init ) ), condition( maybeClone( other.condition ) ), change( maybeClone( other.change ) ) { } ForCtlExprNode::~ForCtlExprNode() { delete init; delete condition; delete change; } Expression *ForCtlExprNode::build() const { // this shouldn't be used! assert( false ); return 0; } void ForCtlExprNode::print( std::ostream &os, int indent ) const{ os << string( indent,' ' ) << "For Control Expression -- :" << endl; os << string( indent + 2, ' ' ) << "initialization:" << endl; if ( init != 0 ) init->printList( os, indent + 4 ); os << string( indent + 2, ' ' ) << "condition: " << endl; if ( condition != 0 ) condition->print( os, indent + 4 ); os << string( indent + 2, ' ' ) << "increment: " << endl; if ( change != 0 ) change->print( os, indent + 4 ); } void ForCtlExprNode::printOneLine( std::ostream &, int indent ) const { assert( false ); } //############################################################################## TypeValueNode::TypeValueNode( DeclarationNode *decl ) : decl( decl ) { } TypeValueNode::TypeValueNode( const TypeValueNode &other ) : ExpressionNode( other ), decl( maybeClone( other.decl ) ) { } Expression *TypeValueNode::build() const { return new TypeExpr( decl->buildType() ); } void TypeValueNode::print( std::ostream &os, int indent ) const { os << std::string( indent, ' ' ) << "Type:"; get_decl()->print( os, indent + 2); } void TypeValueNode::printOneLine( std::ostream &os, int indent ) const { os << "Type:"; get_decl()->print( os, indent + 2); } ExpressionNode *flattenCommas( ExpressionNode *list ) { if ( CompositeExprNode *composite = dynamic_cast< CompositeExprNode * >( list ) ) { OperatorNode *op; if ( ( op = dynamic_cast< OperatorNode * >( composite->get_function() )) && ( op->get_type() == OperatorNode::Comma ) ) { if ( ExpressionNode *next = dynamic_cast< ExpressionNode * >( list->get_link() ) ) composite->add_arg( next ); return flattenCommas( composite->get_args() ); } // if } // if if ( ExpressionNode *next = dynamic_cast< ExpressionNode * >( list->get_link() ) ) list->set_next( flattenCommas( next ) ); return list; } ExpressionNode *tupleContents( ExpressionNode *tuple ) { if ( CompositeExprNode *composite = dynamic_cast< CompositeExprNode * >( tuple ) ) { OperatorNode *op = 0; if ( ( op = dynamic_cast< OperatorNode * >( composite->get_function() )) && ( op->get_type() == OperatorNode::TupleC ) ) return composite->get_args(); } // if return tuple; } // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //