- Timestamp:
- Jun 17, 2019, 11:01:04 AM (6 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- b4d34fa
- Parents:
- 6a1dfda
- Location:
- src
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Convert.cpp
r6a1dfda rc36298d 740 740 741 741 const ast::Expr * visit( const ast::ConstantExpr * node ) override final { 742 ConstantExpr *rslt = nullptr; 743 switch ( node->kind ) { 744 case ast::ConstantExpr::Integer: 745 rslt = new ConstantExpr{Constant{ 746 get<Type>().accept1( node->result ), 747 node->rep, 748 (unsigned long long) node->intValue() 749 }}; 750 break; 751 case ast::ConstantExpr::FloatingPoint: 752 rslt = new ConstantExpr{Constant{ 753 get<Type>().accept1(node->result), 754 node->rep, 755 (double) node->floatValue() 756 }}; 757 break; 758 case ast::ConstantExpr::String: 759 // Old world: two types: rslt->constant.type, rslt->result 760 // New workd: one type: node->result 761 // Both worlds: the outer, expression-level type can change during resolution 762 // in case of string, that's char[k] before-resolve and char * after 763 // Old world: the inner Constant type stays what it was built with 764 // in case of string, that's char[k] 765 // Both worlds: the "rep" field of a string constant is the string value it was initialized from, wrapped in quotes, but not otherwise escaped 766 ast::ptr<ast::Type> charType = nullptr; 767 if (const ast::ArrayType *arrRslt = node->result.as<ast::ArrayType>()) { 768 charType = arrRslt->base; 769 } else { 770 const ast::PointerType *ptrRslt = node->result.as<ast::PointerType>(); 771 assert(ptrRslt); 772 charType = ptrRslt->base; 773 } 774 rslt = new ConstantExpr(Constant::from_string( 775 node->rep, get<Type>().accept1(charType))); // rslt->result is char[k] 776 rslt->set_result( get<Type>().accept1( node->result ) ); // rslt->result is [[ node->rsult ]] 777 break; 778 } 779 assert(rslt); 742 // Old world: two types: rslt->constant.type, rslt->result 743 // New workd: one public type: node->result, plus node->underlyer only to support roundtrip conversion 744 // preserving underlyer because the correct type for string literals is complicated to construct, 745 // and distinguishing a string from other literals using the type is hard to do accurately 746 // Both worlds: the outer, expression-level type can change during resolution 747 // for a string, that's char[k] before-resolve and char * after 748 // Old world: the inner Constant type stays what it was built with 749 // for a string, that's char[k] always 750 // Both worlds: the "rep" field of a constant is the C source file fragment that compiles to the desired value 751 // for a string, that includes outer quotes, backslashes, et al cases from the Literals test 752 ConstantExpr *rslt = new ConstantExpr(Constant( 753 get<Type>().accept1(node->underlyer), 754 node->rep, 755 node->ival)); 780 756 auto expr = visitBaseExpr( node, rslt ); 781 757 this->node = expr; … … 2162 2138 } 2163 2139 2164 bool isIntlikeConstantType(const Type *t) {2165 if ( const BasicType * basicType = dynamic_cast< const BasicType * >( t ) ) {2166 if ( basicType->isInteger() ) {2167 return true;2168 }2169 } else if ( dynamic_cast< const OneType * >( t ) ) {2170 return true;2171 } else if ( dynamic_cast< const ZeroType * >( t ) ) {2172 return true;2173 } else if ( dynamic_cast< const PointerType * >( t ) ) {2174 // null pointer constants, with zero int-values2175 return true;2176 }2177 return false;2178 }2179 2180 int isFloatlikeConstantType(const Type *t) {2181 if ( const BasicType * bty = dynamic_cast< const BasicType * >( t ) ) {2182 if ( ! bty->isInteger() ) {2183 return true;2184 }2185 }2186 return false;2187 }2188 2189 int isStringlikeConstantType(const Type *t) {2190 const Type *referentType = nullptr;2191 if ( const ArrayType * aty = dynamic_cast< const ArrayType * >( t ) ) {2192 referentType = aty->base;2193 } else if ( const PointerType * pty = dynamic_cast< const PointerType * >( t ) ) {2194 referentType = pty->base;2195 }2196 if (referentType) {2197 if ( const BasicType * bty = dynamic_cast< const BasicType * >( referentType ) ) {2198 if ( bty->kind == BasicType::Kind::Char ) {2199 return true;2200 }2201 }2202 }2203 return false;2204 }2205 2206 2140 virtual void visit( ConstantExpr * old ) override final { 2207 ast::ConstantExpr *rslt = nullptr; 2208 if (isStringlikeConstantType(old->result)) { 2209 rslt = new ast::ConstantExpr( 2210 old->location, 2211 GET_ACCEPT_1(result, Type), // preserve the expression-level type (old->result, not old->constant.type); see new-to-old 2212 old->constant.get_value(), 2213 0, 2214 ast::ConstantExpr::Kind::String 2215 ); 2216 } else if (isIntlikeConstantType(old->result)) { 2217 rslt = new ast::ConstantExpr( 2218 old->location, 2219 GET_ACCEPT_1(result, Type), 2220 old->constant.get_value(), 2221 (unsigned long long) old->intValue(), 2222 ast::ConstantExpr::Kind::Integer 2223 ); 2224 } else if (isFloatlikeConstantType(old->result)) { 2225 rslt = new ast::ConstantExpr( 2226 old->location, 2227 GET_ACCEPT_1(result, Type), 2228 old->constant.get_value(), 2229 (double) old->constant.get_dval() 2230 ); 2231 } 2232 assert(rslt); 2141 ast::ConstantExpr *rslt = new ast::ConstantExpr( 2142 old->location, 2143 GET_ACCEPT_1(result, Type), 2144 old->constant.get_value(), 2145 old->constant.ival 2146 ); 2147 rslt->underlyer = getAccept1< ast::Type, Type* >( old->constant.get_type() ); 2233 2148 this->node = visitBaseExpr( old, rslt ); 2234 2149 } -
src/AST/Expr.cpp
r6a1dfda rc36298d 194 194 if ( const BasicType * bty = result.as< BasicType >() ) { 195 195 if ( bty->isInteger() ) { 196 return val.ival; 196 assert(ival); 197 return ival.value(); 197 198 } 198 199 } else if ( result.as< ZeroType >() ) { … … 204 205 } 205 206 206 double ConstantExpr::floatValue() const {207 if ( const BasicType * bty = result.as< BasicType >() ) {208 if ( ! bty->isInteger() ) {209 return val.dval;210 }211 }212 SemanticError( this, "Constant expression of non-floating-point type " );213 }214 215 207 ConstantExpr * ConstantExpr::from_bool( const CodeLocation & loc, bool b ) { 216 208 return new ConstantExpr{ 217 209 loc, new BasicType{ BasicType::Bool }, b ? "1" : "0", (unsigned long long)b }; 218 }219 220 ConstantExpr * ConstantExpr::from_char( const CodeLocation & loc, char c ) {221 return new ConstantExpr{222 loc, new BasicType{ BasicType::Char }, std::to_string( c ), (unsigned long long)c };223 210 } 224 211 … … 232 219 loc, new BasicType{ BasicType::LongUnsignedInt }, std::to_string( i ), 233 220 (unsigned long long)i }; 234 }235 236 ConstantExpr * ConstantExpr::from_double( const CodeLocation & loc, double d ) {237 return new ConstantExpr{ loc, new BasicType{ BasicType::Double }, std::to_string( d ), d };238 221 } 239 222 -
src/AST/Expr.hpp
r6a1dfda rc36298d 22 22 #include <utility> // for move 23 23 #include <vector> 24 #include <optional> 24 25 25 26 #include "Fwd.hpp" // for UniqueId … … 32 33 33 34 class ConverterOldToNew; 35 class ConverterNewToOld; 34 36 35 37 namespace ast { … … 346 348 }; 347 349 348 /// A compile-time constant 350 /// A compile-time constant. 351 /// Mostly carries C-source text from parse to code-gen, without interpretation. E.g. strings keep their outer quotes and never have backslashes interpreted. 352 /// Integer constants get special treatment, e.g. for verifying array operations, when an integer constant occurs as the length of an array. 349 353 class ConstantExpr final : public Expr { 350 union Val { 351 unsigned long long ival; 352 double dval; 353 354 Val( unsigned long long i ) : ival( i ) {} 355 Val( double d ) : dval( d ) {} 356 } val; 357 public: 354 public: 355 // Representation of this constant, as it occurs in .cfa source and .cfa.cc result. 358 356 std::string rep; 359 enum Kind { Integer, FloatingPoint, String } kind;360 357 361 358 ConstantExpr( 362 const CodeLocation & loc, const Type * ty, const std::string & r, unsigned long long v,363 Kind k = Integer)364 : Expr( loc, ty ), val( v ), rep( r ), kind( k) {}365 ConstantExpr( const CodeLocation & loc, const Type * ty, const std::string & r, double v ) 366 : Expr( loc, ty ), val( v ), rep( r ), kind( FloatingPoint ) {}367 368 /// Gets the value of this constant as an integer359 const CodeLocation & loc, const Type * ty, const std::string & r, 360 std::optional<unsigned long long> i ) 361 : Expr( loc, ty ), rep( r ), ival( i ) {} 362 363 /// Gets the integer value of this constant, if one is appropriate to its type. 364 /// Throws a SemanticError if the type is not appropriate for value-as-integer. 365 /// Suffers an assertion failure the type is appropriate but no integer value was supplied to the constructor. 369 366 long long int intValue() const; 370 /// Gets the value of this constant as floating point371 double floatValue() const;372 367 373 368 /// generates a boolean constant of the given bool 374 369 static ConstantExpr * from_bool( const CodeLocation & loc, bool b ); 375 /// generates a char constant of the given char376 static ConstantExpr * from_char( const CodeLocation & loc, char c );377 370 /// generates an integer constant of the given int 378 371 static ConstantExpr * from_int( const CodeLocation & loc, int i ); 379 372 /// generates an integer constant of the given unsigned long int 380 373 static ConstantExpr * from_ulong( const CodeLocation & loc, unsigned long i ); 381 /// generates a floating point constant of the given double382 static ConstantExpr * from_double( const CodeLocation & loc, double d );383 374 /// generates a null pointer value for the given type. void * if omitted. 384 375 static ConstantExpr * null( const CodeLocation & loc, const Type * ptrType = nullptr ); … … 388 379 ConstantExpr * clone() const override { return new ConstantExpr{ *this }; } 389 380 MUTATE_FRIEND 381 382 std::optional<unsigned long long> ival; 383 384 // Intended only for legacy support of roundtripping the old AST. 385 // Captures the very-locally inferred type, before the resolver modifies the type of this ConstantExpression. 386 // In the old AST it's constExpr->constant.type 387 ptr<Type> underlyer; 388 friend class ::ConverterOldToNew; 389 friend class ::ConverterNewToOld; 390 390 }; 391 391 -
src/Parser/ExpressionNode.cc
r6a1dfda rc36298d 354 354 strtype = new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char ); 355 355 } // switch 356 Expression * ret = new ConstantExpr( Constant::from_string( str, strtype ) ); 356 ArrayType * at = new ArrayType( noQualifiers, strtype, 357 new ConstantExpr( Constant::from_ulong( str.size() + 1 - 2 ) ), // +1 for '\0' and -2 for '"' 358 false, false ); 359 Expression * ret = new ConstantExpr( Constant( at, str, std::nullopt ) ); 357 360 if ( units.length() != 0 ) { 358 361 ret = new UntypedExpr( new NameExpr( units ), { ret } ); -
src/SynTree/Constant.cc
r6a1dfda rc36298d 22 22 #include "Type.h" // for BasicType, Type, Type::Qualifiers, PointerType 23 23 24 Constant::Constant( Type * type, std::string rep, unsigned long long val ) : type( type ), rep( rep ), val( val ) {} 25 Constant::Constant( Type * type, std::string rep, double val ) : type( type ), rep( rep ), val( val ) {} 24 Constant::Constant( Type * type, std::string rep, std::optional<unsigned long long> ival ) : type( type ), rep( rep ), ival( ival ) {} 26 25 27 Constant::Constant( const Constant &other ) : BaseSyntaxNode( other ), rep( other.rep ), val( other.val ) {26 Constant::Constant( const Constant &other ) : BaseSyntaxNode( other ), rep( other.rep ), ival( other.ival ) { 28 27 type = other.type->clone(); 29 28 } … … 35 34 } 36 35 37 Constant Constant::from_char( char c ) {38 return Constant( new BasicType( Type::Qualifiers(), BasicType::Char ), std::to_string( c ), (unsigned long long int)c );39 }40 41 36 Constant Constant::from_int( int i ) { 42 37 return Constant( new BasicType( Type::Qualifiers(), BasicType::SignedInt ), std::to_string( i ), (unsigned long long int)i ); … … 45 40 Constant Constant::from_ulong( unsigned long i ) { 46 41 return Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), std::to_string( i ), (unsigned long long int)i ); 47 }48 49 Constant Constant::from_double( double d ) {50 return Constant( new BasicType( Type::Qualifiers(), BasicType::Double ), std::to_string( d ), d );51 }52 53 Constant Constant::from_string( std::string const & cEscapedVal, Type *charType ) {54 assert(cEscapedVal.length() >= 2);55 assert(cEscapedVal.front() == '"');56 assert(cEscapedVal.back() == '"');57 ArrayType * at = new ArrayType( noQualifiers, charType,58 new ConstantExpr( Constant::from_ulong( cEscapedVal.size() + 1 - 2 ) ), // +1 for '\0' and -2 for '"'59 false, false );60 return Constant( at, cEscapedVal, (unsigned long long int)0 );61 42 } 62 43 … … 74 55 unsigned long long Constant::get_ival() const { 75 56 assertf( strict_dynamic_cast<BasicType*>(type)->isInteger(), "Attempt to retrieve ival from non-integer constant." ); 76 return val.ival; 77 } 78 79 double Constant::get_dval() const { 80 assertf( ! strict_dynamic_cast<BasicType*>(type)->isInteger(), "Attempt to retrieve dval from integer constant." ); 81 return val.dval; 57 return ival.value(); 82 58 } 83 59 84 60 void Constant::print( std::ostream &os, Indenter ) const { 85 os << "(" << rep << " " << val.ival;61 os << "(" << rep << " " << (ival ? toString(ival.value()) : "") ; 86 62 if ( type ) { 87 63 os << ": "; -
src/SynTree/Constant.h
r6a1dfda rc36298d 18 18 #include <iosfwd> // for ostream 19 19 #include <string> // for string 20 #include <optional> // for optional 20 21 21 22 #include "BaseSyntaxNode.h" … … 27 28 class Constant : public BaseSyntaxNode { 28 29 public: 29 Constant( Type * type, std::string rep, unsigned long long val ); 30 Constant( Type * type, std::string rep, double val ); 30 Constant( Type * type, std::string rep, std::optional<unsigned long long> i ); 31 31 Constant( const Constant & other ); 32 32 virtual ~Constant(); … … 39 39 void set_value( std::string newValue ) { rep = newValue; } 40 40 unsigned long long get_ival() const; 41 double get_dval() const;42 41 43 42 /// generates a boolean constant of the given bool 44 43 static Constant from_bool( bool b ); 45 /// generates a char constant of the given char46 static Constant from_char( char c );47 44 /// generates an integer constant of the given int 48 45 static Constant from_int( int i ); 49 46 /// generates an integer constant of the given unsigned long int 50 47 static Constant from_ulong( unsigned long i ); 51 /// generates a floating point constant of the given double52 static Constant from_double( double d );53 /// generates an array of chars constant of the given string54 static Constant from_string( std::string const & cEscapedVal, Type *charType );55 48 56 49 /// generates a null pointer value for the given type. void * if omitted. … … 63 56 Type * type; 64 57 std::string rep; 65 union Val { 66 unsigned long long ival; 67 double dval; 68 Val( unsigned long long ival ) : ival( ival ) {} 69 Val( double dval ) : dval( dval ) {} 70 } val; 58 std::optional<unsigned long long> ival; 59 60 friend class ConverterOldToNew; 71 61 }; 72 62
Note: See TracChangeset
for help on using the changeset viewer.