// // 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 : Peter A. Buhr // Last Modified On : Fri Aug 5 11:39:25 2016 // Update Count : 391 // #include #include #include #include #include #include "ParseNode.h" #include "TypeData.h" #include "SynTree/Constant.h" #include "SynTree/Expression.h" #include "SynTree/Declaration.h" #include "Common/UnimplementedError.h" #include "parseutility.h" #include "Common/utility.h" using namespace std; ExpressionNode::ExpressionNode() : ParseNode() {} ExpressionNode::ExpressionNode( const string *name ) : ParseNode( name ) {} ExpressionNode::ExpressionNode( const ExpressionNode &other ) : ParseNode( other.name ), extension( other.extension ) { 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 ); // } //############################################################################## ConstantNode::ConstantNode( ConstantExpr *expr ) : expr( expr ) { } // ConstantNode::ConstantNode ConstantNode *ConstantNode::appendstr( const std::string *newValue ) { assert( newValue != 0 ); string value = expr->get_constant()->get_value(); // "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 ) ); expr->get_constant()->set_value( value ); 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 { return expr->clone(); } //############################################################################## 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 = maybeBuild(get_argName()); 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 } //############################################################################## static const char *opName[] = { "TupleC", "Comma", "TupleFieldSel", // "TuplePFieldSel", // n-adic // triadic "Cond", "NCond", // diadic "SizeOf", "AlignOf", "OffsetOf", "Attr", "?+?", "?-?", "?*?", "?/?", "?%?", "||", "&&", "?|?", "?&?", "?^?", "Cast", "?<>?", "??", "?<=?", "?>=?", "?==?", "?!=?", "?=?", "?*=?", "?/=?", "?%=?", "?+=?", "?-=?", "?<<=?", "?>>=?", "?&=?", "?^=?", "?|=?", "?[?]", "FieldSel", "PFieldSel", "...", // monadic "+?", "-?", "AddressOf", "*?", "!?", "~?", "++?", "?++", "--?", "?--", "&&" }; 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 ]; } //############################################################################## 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 ) ), arguments( 0 ) { 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; } Expression *build_cast( TypeValueNode * arg, ExpressionNode *expr_node ) { DeclarationNode *decl_node = arg->get_decl(); Type *targetType = decl_node->buildType(); if ( dynamic_cast< VoidType* >( targetType ) ) { delete targetType; return new CastExpr( maybeBuild(expr_node) ); } else { return new CastExpr( maybeBuild(expr_node), targetType ); } // if } Expression *build_fieldSel( ExpressionNode *expr_node, VarRefNode *member ) { NameExpr* memberExpr = dynamic_cast ( maybeBuild( member) ); assert( memberExpr ); UntypedMemberExpr *ret = new UntypedMemberExpr( memberExpr->get_name(), maybeBuild(expr_node) ); delete member; return ret; } Expression *build_pfieldSel( ExpressionNode *expr_node, VarRefNode *member ) { NameExpr* memberExpr = dynamic_cast ( maybeBuild( member) ); assert( memberExpr ); UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); deref->get_args().push_back( maybeBuild(expr_node) ); UntypedMemberExpr *ret = new UntypedMemberExpr( memberExpr->get_name(), deref ); delete member; return ret; } Expression *build_addressOf( ExpressionNode *expr_node ) { return new AddressExpr( maybeBuild(expr_node) ); } Expression *build_sizeOf( ExpressionNode *expr_node ) { if ( TypeValueNode * arg = dynamic_cast( expr_node ) ) { return new SizeofExpr( arg->get_decl()->buildType() ); } else { return new SizeofExpr( maybeBuild(expr_node) ); } // if } Expression *build_alignOf( ExpressionNode *expr_node ) { if ( TypeValueNode * arg = dynamic_cast( expr_node ) ) { return new AlignofExpr( arg->get_decl()->buildType() ); } else { return new AlignofExpr( maybeBuild(expr_node) ); } // if } Expression *build_offsetOf( TypeValueNode * arg, VarRefNode *member ) { NameExpr *memberExpr = dynamic_cast( maybeBuild( member ) ); assert( memberExpr ); return new UntypedOffsetofExpr( arg->get_decl()->buildType(), memberExpr->get_name() ); } Expression *build_and_or( ExpressionNode *expr_node1, ExpressionNode *expr_node2, bool kind ) { return new LogicalExpr( notZeroExpr( maybeBuild(expr_node1) ), notZeroExpr( maybeBuild(expr_node2) ), kind ); } Expression *build_unary_val( OperatorNode::Type op, ExpressionNode *expr_node ) { std::list args; args.push_back( maybeBuild(expr_node) ); return new UntypedExpr( new NameExpr( opName[ op ] ), args ); } Expression *build_unary_ptr( OperatorNode::Type op, ExpressionNode *expr_node ) { std::list args; args.push_back( new AddressExpr( maybeBuild(expr_node) ) ); return new UntypedExpr( new NameExpr( opName[ op ] ), args ); } Expression *build_binary_val( OperatorNode::Type op, ExpressionNode *expr_node1, ExpressionNode *expr_node2 ) { std::list args; args.push_back( maybeBuild(expr_node1) ); args.push_back( maybeBuild(expr_node2) ); return new UntypedExpr( new NameExpr( opName[ op ] ), args ); } Expression *build_binary_ptr( OperatorNode::Type op, ExpressionNode *expr_node1, ExpressionNode *expr_node2 ) { std::list args; args.push_back( new AddressExpr( maybeBuild(expr_node1) ) ); args.push_back( maybeBuild(expr_node2) ); return new UntypedExpr( new NameExpr( opName[ op ] ), args ); } Expression *build_cond( ExpressionNode *expr_node1, ExpressionNode *expr_node2, ExpressionNode *expr_node3 ) { return new ConditionalExpr( notZeroExpr( maybeBuild(expr_node1) ), maybeBuild(expr_node2), maybeBuild(expr_node3) ); } Expression *build_comma( ExpressionNode *expr_node1, ExpressionNode *expr_node2 ) { return new CommaExpr( maybeBuild(expr_node1), maybeBuild(expr_node2) ); } Expression *build_attr( VarRefNode *var, ExpressionNode * expr ) { if ( TypeValueNode * arg = dynamic_cast( expr ) ) { return new AttrExpr( maybeBuild(var), arg->get_decl()->buildType() ); } else { return new AttrExpr( maybeBuild(var), maybeBuild(expr) ); } // if } Expression *build_tuple( ExpressionNode * expr ) { TupleExpr *ret = new TupleExpr(); buildList( expr, ret->get_exprs() ); return ret; } Expression *build_func( ExpressionNode * function, ExpressionNode * expr ) { std::list args; buildList( expr, args ); return new UntypedExpr( maybeBuild(function), args, nullptr ); } CompositeExprNode2::CompositeExprNode2( Expression *expr ) : expr( expr ) {} CompositeExprNode2::CompositeExprNode2( const CompositeExprNode2 &other ) : expr( other.expr->clone() ) {} CompositeExprNode2::~CompositeExprNode2() { delete expr; } void CompositeExprNode2::print( std::ostream &, int indent ) const { assert( false ); } void CompositeExprNode2::printOneLine( std::ostream &, int indent ) const { assert( false ); } 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( maybeBuild(function), args, maybeBuild< Expression >( get_argName() )); } // if assert( ((void)"CompositeExprNode::build", false) ); return nullptr; } 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 ); } // for 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 *)maybeBuild(constraint), maybeBuild(operand) ); } 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 ( maybeBuild(get_body()), 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); } CompoundLiteralNode::CompoundLiteralNode( DeclarationNode *type, InitializerNode *kids ) : type( type ), kids( kids ) {} CompoundLiteralNode::CompoundLiteralNode( const CompoundLiteralNode &other ) : ExpressionNode( other ), type( other.type ), kids( other.kids ) {} CompoundLiteralNode::~CompoundLiteralNode() { delete kids; delete type; } CompoundLiteralNode *CompoundLiteralNode::clone() const { return new CompoundLiteralNode( *this ); } void CompoundLiteralNode::print( std::ostream &os, int indent ) const { os << string( indent,' ' ) << "CompoundLiteralNode:" << endl; os << string( indent + 2, ' ' ) << "type:" << endl; if ( type != 0 ) type->print( os, indent + 4 ); os << string( indent + 2, ' ' ) << "initialization:" << endl; if ( kids != 0 ) kids->printList( os, indent + 4 ); } void CompoundLiteralNode::printOneLine( std::ostream &os, int indent ) const { os << "( "; if ( type ) type->print( os ); os << ", "; if ( kids ) kids->printOneLine( os ); os << ") "; } Expression *CompoundLiteralNode::build() const { Declaration * newDecl = maybeBuild(type); // compound literal type if ( DeclarationWithType * newDeclWithType = dynamic_cast< DeclarationWithType * >( newDecl ) ) { // non-sue compound-literal type return new CompoundLiteralExpr( newDeclWithType->get_type(), maybeBuild(kids) ); // these types do not have associated type information } else if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( newDecl ) ) { return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() ), maybeBuild(kids) ); } else if ( UnionDecl * newDeclUnionDecl = dynamic_cast< UnionDecl * >( newDecl ) ) { return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl->get_name() ), maybeBuild(kids) ); } else if ( EnumDecl * newDeclEnumDecl = dynamic_cast< EnumDecl * >( newDecl ) ) { return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() ), maybeBuild(kids) ); } else { assert( false ); } // if } 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: //