// // 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 : Wed Aug 10 11:07:38 2016 // Update Count : 486 // #include #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( const ExpressionNode &other ) : ParseNode( other.name ), extension( other.extension ) {} //############################################################################## // 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. static Type::Qualifiers emptyQualifiers; // no qualifiers on constants 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 checkD( char c ) { return c == 'd' || c == 'D'; } static inline bool checkI( char c ) { return c == 'i' || c == 'I'; } static inline bool checkX( char c ) { return c == 'x' || c == 'X'; } Expression *build_constantInteger( std::string & str ) { static const BasicType::Kind kind[2][3] = { { BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt }, { BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt }, }; bool dec = true, Unsigned = false; // decimal, unsigned constant int size; // 0 => int, 1 => long, 2 => long long unsigned long long v; // converted integral value size_t last = str.length() - 1; // last character of constant if ( str[0] == '0' ) { // octal/hex constant ? dec = false; if ( last != 0 && checkX( str[1] ) ) { // hex constant ? sscanf( (char *)str.c_str(), "%llx", &v ); //printf( "%llx %llu\n", v, v ); } else { // octal constant sscanf( (char *)str.c_str(), "%llo", &v ); //printf( "%llo %llu\n", v, v ); } // if } else { // decimal constant ? sscanf( (char *)str.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( str[last] ) ) { // suffix 'u' ? Unsigned = true; if ( last > 0 && checkL( str[last - 1] ) ) { // suffix 'l' ? size = 1; if ( last > 1 && checkL( str[last - 2] ) ) { // suffix 'll' ? size = 2; } // if } // if } else if ( checkL( str[ last ] ) ) { // suffix 'l' ? size = 1; if ( last > 0 && checkL( str[last - 1] ) ) { // suffix 'll' ? size = 2; if ( last > 1 && checkU( str[last - 2] ) ) { // suffix 'u' ? Unsigned = true; } // if } else { if ( last > 0 && checkU( str[last - 1] ) ) { // suffix 'u' ? Unsigned = true; } // if } // if } // if return new ConstantExpr( Constant( new BasicType( emptyQualifiers, kind[Unsigned][size] ), str ) ); } // build_constantInteger Expression *build_constantFloat( std::string & str ) { static const BasicType::Kind kind[2][3] = { { BasicType::Float, BasicType::Double, BasicType::LongDouble }, { BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex }, }; bool complx = false; // real, complex int size = 1; // 0 => float, 1 => double (default), 2 => long double // floating-point constant has minimum of 2 characters: 1. or .1 size_t last = str.length() - 1; if ( checkI( str[last] ) ) { // imaginary ? complx = true; last -= 1; // backup one character } // if if ( checkF( str[last] ) ) { // float ? size = 0; } else if ( checkD( str[last] ) ) { // double ? size = 1; } else if ( checkL( str[last] ) ) { // long double ? size = 2; } // if if ( ! complx && checkI( str[last - 1] ) ) { // imaginary ? complx = true; } // if return new ConstantExpr( Constant( new BasicType( emptyQualifiers, kind[complx][size] ), str ) ); } // build_constantFloat Expression *build_constantChar( std::string & str ) { return new ConstantExpr( Constant( new BasicType( emptyQualifiers, BasicType::Char ), str ) ); } // build_constantChar ConstantExpr *build_constantStr( std::string & str ) { // string should probably be a primitive type ArrayType *at = new ArrayType( emptyQualifiers, new BasicType( emptyQualifiers, BasicType::Char ), new ConstantExpr( Constant( new BasicType( emptyQualifiers, BasicType::UnsignedInt ), toString( str.size()+1-2 ) ) ), // +1 for '\0' and -2 for '"' false, false ); return new ConstantExpr( Constant( at, str ) ); } // build_constantStr //############################################################################## NameExpr * build_varref( const string *name, bool labelp ) { return new NameExpr( *name, nullptr ); } //############################################################################## static const char *OperName[] = { // diadic "SizeOf", "AlignOf", "OffsetOf", "?+?", "?-?", "?*?", "?/?", "?%?", "||", "&&", "?|?", "?&?", "?^?", "Cast", "?<>?", "??", "?<=?", "?>=?", "?==?", "?!=?", "?=?", "?*=?", "?/=?", "?%=?", "?+=?", "?-=?", "?<<=?", "?>>=?", "?&=?", "?^=?", "?|=?", "?[?]", "...", // monadic "+?", "-?", "AddressOf", "*?", "!?", "~?", "++?", "?++", "--?", "?--", "&&" }; //############################################################################## Expression *build_cast( DeclarationNode *decl_node, ExpressionNode *expr_node ) { 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, NameExpr *member ) { UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), maybeBuild(expr_node) ); delete member; return ret; } Expression *build_pfieldSel( ExpressionNode *expr_node, NameExpr *member ) { UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); deref->get_args().push_back( maybeBuild(expr_node) ); UntypedMemberExpr *ret = new UntypedMemberExpr( member->get_name(), deref ); delete member; return ret; } Expression *build_addressOf( ExpressionNode *expr_node ) { return new AddressExpr( maybeBuild(expr_node) ); } Expression *build_sizeOfexpr( ExpressionNode *expr_node ) { return new SizeofExpr( maybeBuild(expr_node) ); } Expression *build_sizeOftype( DeclarationNode *decl_node ) { return new SizeofExpr( decl_node->buildType() ); } Expression *build_alignOfexpr( ExpressionNode *expr_node ) { return new AlignofExpr( maybeBuild(expr_node) ); } Expression *build_alignOftype( DeclarationNode *decl_node ) { return new AlignofExpr( decl_node->buildType() ); } Expression *build_offsetOf( DeclarationNode *decl_node, NameExpr *member ) { return new UntypedOffsetofExpr( decl_node->buildType(), member->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( OperKinds op, ExpressionNode *expr_node ) { std::list args; args.push_back( maybeBuild(expr_node) ); return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); } Expression *build_unary_ptr( OperKinds op, ExpressionNode *expr_node ) { std::list args; args.push_back( new AddressExpr( maybeBuild(expr_node) ) ); return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); } Expression *build_binary_val( OperKinds 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( OperName[ (int)op ] ), args ); } Expression *build_binary_ptr( OperKinds 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( OperName[ (int)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_attrexpr( NameExpr *var, ExpressionNode * expr_node ) { return new AttrExpr( var, maybeBuild(expr_node) ); } Expression *build_attrtype( NameExpr *var, DeclarationNode * decl_node ) { return new AttrExpr( var, decl_node->buildType() ); } Expression *build_tuple( ExpressionNode * expr_node ) { TupleExpr *ret = new TupleExpr(); buildList( expr_node, ret->get_exprs() ); return ret; } Expression *build_func( ExpressionNode * function, ExpressionNode * expr_node ) { std::list args; buildList( expr_node, args ); return new UntypedExpr( maybeBuild(function), args, nullptr ); } Expression *build_range( ExpressionNode * low, ExpressionNode *high ) { Expression *low_cexpr = maybeBuild( low ); Expression *high_cexpr = maybeBuild( high ); return new RangeExpr( low_cexpr, high_cexpr ); } //############################################################################## Expression *build_asm( ExpressionNode *inout, ConstantExpr *constraint, ExpressionNode *operand ) { return new AsmExpr( maybeBuild< Expression >( inout ), constraint, maybeBuild(operand) ); } //############################################################################## void LabelNode::print( std::ostream &os, int indent ) const {} void LabelNode::printOneLine( std::ostream &os, int indent ) const {} //############################################################################## Expression *build_valexpr( StatementNode *s ) { return new UntypedValofExpr( maybeBuild(s), nullptr ); } //############################################################################## // 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 ); // } //############################################################################## Expression *build_typevalue( DeclarationNode *decl ) { return new TypeExpr( decl->buildType() ); } //############################################################################## Expression *build_compoundLiteral( DeclarationNode *decl_node, InitializerNode *kids ) { Declaration * newDecl = maybeBuild(decl_node); // 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 } // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //