Changes in / [bc07190:62a38e7]
- Files:
-
- 18 edited
-
libcfa/src/enum.cfa (modified) (1 diff)
-
libcfa/src/enum.hfa (modified) (2 diffs)
-
src/AST/Decl.cpp (modified) (1 diff)
-
src/AST/Decl.hpp (modified) (2 diffs)
-
src/AST/Stmt.hpp (modified) (2 diffs)
-
src/Common/Stats/Heap.cpp (modified) (1 diff)
-
src/ControlStruct/TranslateEnumRange.cpp (modified) (3 diffs)
-
src/Parser/StatementNode.cpp (modified) (1 diff)
-
src/Parser/StatementNode.hpp (modified) (2 diffs)
-
src/Parser/TypeData.cpp (modified) (1 diff)
-
src/Parser/lex.ll (modified) (2 diffs)
-
src/Parser/parser.yy (modified) (13 diffs)
-
src/ResolvExpr/CandidateFinder.cpp (modified) (4 diffs)
-
src/ResolvExpr/CastCost.cpp (modified) (4 diffs)
-
src/ResolvExpr/CommonType.cpp (modified) (2 diffs)
-
src/ResolvExpr/ConversionCost.cpp (modified) (6 diffs)
-
src/ResolvExpr/Unify.cpp (modified) (5 diffs)
-
src/Validate/ImplementEnumFunc.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/enum.cfa
rbc07190 r62a38e7 4 4 #pragma GCC visibility push(default) 5 5 6 forall( ostype & | basic_ostream(ostype), E, V | CfaEnum(E, V) ) { 7 ostype & ?|?( ostype& os, E e ) { 8 return os | label( e ); 9 } 10 OSTYPE_VOID_IMPL( E ) 6 forall(ostype & | basic_ostream(ostype), E, V| CfaEnum(E, V)) 7 ostype & ?|?(ostype& os, E e) { 8 return os | type_name(e) | "." | label(e); 11 9 } 12 10 13 forall( ostype & | basic_ostream(ostype), E | CfaEnum(E, quasi_void))14 ostype & ?|?( ostype & os, E e) {15 return os | label( e);11 forall(ostype & | basic_ostream(ostype), E| CfaEnum(E, quasi_void)) 12 ostype & ?|?(ostype& os, E e) { 13 return os | type_name(e) | "." | label(e); 16 14 } 17 15 18 forall( E, V | CfaEnum(E, V) ) { // relational operators16 forall(ostype & | basic_ostream(ostype), E, V| CfaEnum(E, V)) { 19 17 int ?==?(E l, E r) { return posn(l) == posn(r); } 20 int ?!=?(E l, E r) { return posn(l) != posn(r); } 18 int ?<=?(E l, E r) { return posn(l) <= posn(r); } 19 int ?>=?(E l, E r) { return posn(l) >= posn(r); } 21 20 int ?<?(E l, E r) { return posn(l) < posn(r); } 22 int ?<=?(E l, E r) { return posn(l) <= posn(r); }23 21 int ?>?(E l, E r) { return posn(l) > posn(r); } 24 int ?>=?(E l, E r) { return posn(l) >= posn(r); }25 22 } -
libcfa/src/enum.hfa
rbc07190 r62a38e7 3 3 #include "iostream.hfa" 4 4 5 forall( E) trait Bounded {5 forall(E) trait Bounded { 6 6 E lowerBound(); 7 7 E upperBound(); 8 8 }; 9 9 10 forall( E | Bounded(E)) trait Serial {11 unsigned fromInstance( E e);12 E fromInt( unsigned i);13 E succ( E e);14 E pred( E e);10 forall(E | Bounded(E)) trait Serial { 11 unsigned fromInstance(E e); 12 E fromInt(unsigned i); 13 E succ(E e); 14 E pred(E e); 15 15 }; 16 16 17 17 // Design one 18 forall( E, V | Serial(E) ) trait CfaEnum { 19 char * label( E e ); 20 unsigned int posn( E e ); 21 V value( E e ); 18 forall(E, V | Serial(E)) trait CfaEnum { 19 char * label(E e); 20 unsigned int posn(E e); 21 V value(E e); 22 char * type_name(E e); 22 23 }; 23 24 24 // I/O 25 forall(ostype & | basic_ostream(ostype), E, V | CfaEnum(E, V)) 26 ostype & ?|?(ostype&, E); 25 27 26 forall( ostype & | basic_ostream(ostype), E, V | CfaEnum(E, V) ) { 27 ostype & ?|?( ostype &, E ); 28 OSTYPE_VOID( E ); 29 } 30 31 forall( ostype & | basic_ostream(ostype), E | CfaEnum(E, quasi_void) ) 32 ostype & ?|?( ostype &, E ); 28 forall(ostype & | basic_ostream(ostype), E| CfaEnum(E, quasi_void)) 29 ostype & ?|?(ostype&, E); 33 30 34 31 // Design two <- should go for this if we have change the cost model … … 42 39 // }; 43 40 44 forall( E, V | CfaEnum(E, V) ) { // relational operators41 forall(ostype & | basic_ostream(ostype), E, V| CfaEnum(E, V)) { 45 42 int ?==?(E, E); 46 int ?!=?(E, E); 43 int ?<=?(E, E); 44 int ?>=?(E, E); 47 45 int ?<?(E, E); 48 int ?<=?(E, E);49 46 int ?>?(E, E); 50 int ?>=?(E, E); 47 48 // E ++?( E & lhs ); 49 // E ?++( E & lhs ); 51 50 } -
src/AST/Decl.cpp
rbc07190 r62a38e7 203 203 } 204 204 205 bool EnumDecl::isTyped() const { return base;}206 207 bool EnumDecl::isOpague() const { return isCfa && !isTyped(); }208 205 } 209 206 -
src/AST/Decl.hpp
rbc07190 r62a38e7 308 308 class EnumDecl final : public AggregateDecl { 309 309 public: 310 // is Cfaindicated if the enum has a declaration like:310 // isTyped indicated if the enum has a declaration like: 311 311 // enum (type_optional) Name {...} 312 bool is Cfa;313 // if is Cfa == true && base.get() == nullptr, it is a "opague"enum312 bool isTyped; 313 // if isTyped == true && base.get() == nullptr, it is a "void" type enum 314 314 ptr<Type> base; 315 315 enum class EnumHiding { Visible, Hide } hide; 316 316 std::vector< ast::ptr<ast::EnumInstType>> inlinedDecl; // child enums 317 317 318 EnumDecl( const CodeLocation& loc, const std::string& name, bool is Cfa= false,318 EnumDecl( const CodeLocation& loc, const std::string& name, bool isTyped = false, 319 319 std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall, 320 320 Type const * base = nullptr, EnumHiding hide = EnumHiding::Hide, 321 321 std::unordered_map< std::string, long long > enumValues = std::unordered_map< std::string, long long >() ) 322 : AggregateDecl( loc, name, std::move(attrs), linkage ), is Cfa(isCfa), base(base), hide(hide), enumValues(enumValues) {}322 : AggregateDecl( loc, name, std::move(attrs), linkage ), isTyped(isTyped), base(base), hide(hide), enumValues(enumValues) {} 323 323 324 324 /// gets the integer value for this enumerator, returning true iff value found … … 336 336 337 337 bool isSubTypeOf(const ast::EnumDecl *) const; 338 bool isTyped() const;339 bool isOpague() const;340 338 private: 341 339 EnumDecl * clone() const override { return new EnumDecl{ *this }; } -
src/AST/Stmt.hpp
rbc07190 r62a38e7 238 238 ptr<Expr> inc; 239 239 ptr<Expr> range_over; 240 bool is_inc;241 240 ptr<Stmt> body; 242 241 ptr<Stmt> else_; … … 252 251 range_over(nullptr), body(body), else_(else_) {} 253 252 254 ForStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits, const Expr * range_over, bool is_inc,253 ForStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits, const Expr * range_over, 255 254 const Stmt * body, const Stmt * else_ ) 256 : Stmt(loc, std::move(labels)), inits(std::move(inits)), range_over(range_over), is_inc(is_inc), 257 body(body), else_(else_) {} 255 : Stmt(loc, std::move(labels)), inits(std::move(inits)), range_over(range_over), body(body), else_(else_) {} 258 256 259 257 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); } -
src/Common/Stats/Heap.cpp
rbc07190 r62a38e7 21 21 #include <iostream> 22 22 23 // Most of the other statistics features are deactivated only by defining 24 // NO_STATISTICS (or their NO_%_STATISTICS macro). However the heap has some 25 // other compatability concerns and will disable itself in some cases. 26 // 27 // I do not claim to understand these cases. But TCMALLOC is often defined by 28 // default and you can pass --disable-gprofiler to configure to remove it. 29 30 #if defined(NO_STATISTICS) || defined(TCMALLOC) || defined(__SANITIZE_ADDRESS__) 31 #define NO_HEAP_STATISTICS 32 #elif defined(__has_feature) 23 #if defined(__has_feature) 33 24 #if __has_feature(address_sanitizer) 25 #define NO_HEAP_STATISTICS 26 # endif 27 #endif 28 29 #if defined( NO_STATISTICS ) || defined( TCMALLOC ) || defined(__SANITIZE_ADDRESS__) 30 #if !defined(NO_HEAP_STATISTICS) 34 31 #define NO_HEAP_STATISTICS 35 32 #endif -
src/ControlStruct/TranslateEnumRange.cpp
rbc07190 r62a38e7 26 26 auto enumDecl = enumInst->base; 27 27 28 auto objInit = stmt->inits.front();28 auto init = stmt->inits.front(); 29 29 30 auto initLocation = objInit->location; 31 auto rangeLocation = stmt->range_over->location; 32 assert( stmt->inits.size() == 1 ); 33 34 if (auto declStmt = objInit.as<ast::DeclStmt>()) { 30 if (auto declStmt = init.as<ast::DeclStmt>()) { 35 31 auto decl = declStmt->decl; 36 32 if ( auto objDecl = decl.as<ast::ObjectDecl>()) { … … 61 57 if ( !objDecl->init ) { 62 58 auto location = stmt->location; 63 ast::SingleInit * newInit; 64 newInit = new ast::SingleInit( location, 65 new ast::NameExpr( location, 66 stmt->is_inc? enumDecl->members.front()->name: enumDecl->members.back()->name ) ); 59 auto newInit = new ast::SingleInit( location, new ast::NameExpr( location, enumDecl->members.front()->name ) ); 67 60 auto objDeclWithInit = ast::mutate_field( objDecl, &ast::ObjectDecl::init, newInit ); 68 61 auto declWithInit = ast::mutate_field( declStmt, &ast::DeclStmt::decl, objDeclWithInit ); … … 85 78 auto enumInst = typeExpr->type.strict_as<ast::EnumInstType>(); 86 79 auto enumDecl = enumInst->base; 87 88 // Both inc and dec check if the current posn less than the number of enumerator89 // for dec, it keeps call pred until it passes 0 (the first enumerator) and underflow,90 // it wraps around and become unsigned max91 ast::UntypedExpr * condition = ast::UntypedExpr::createCall( location,92 "?<=?",93 {new ast::CastExpr(location,94 new ast::NameExpr( location, indexName ),95 new ast::BasicType( ast::BasicKind::UnsignedInt ),96 ast::GeneratedFlag::ExplicitCast),97 ast::ConstantExpr::from_ulong( location, enumDecl->members.size()-1 ) });98 80 99 auto increment = ast::UntypedExpr::createCall( location, 100 stmt->is_inc? "?++": "?--", 101 { new ast::NameExpr( location, indexName ) }); 102 81 auto condition = ast::UntypedExpr::createCall( location, "?<=?", { 82 new ast::NameExpr( location, indexName ), 83 // ast::ConstantExpr::from_ulong( location, enumDecl->members.size() ) 84 new ast::NameExpr( location, enumDecl->members.back()->name ) 85 }); 86 auto increment = ast::UntypedExpr::createCall( location, "succ", { 87 new ast::NameExpr( location, indexName ) 88 }); 103 89 auto assig = ast::UntypedExpr::createAssign( location, new ast::NameExpr( location, indexName ), increment ); 104 90 auto mut = ast::mutate_field( stmt, &ast::ForStmt::cond, condition ); -
src/Parser/StatementNode.cpp
rbc07190 r62a38e7 216 216 return new ast::ForStmt( location, 217 217 std::move( astinit ), 218 range_over, forctl->kind == OperKinds::LThan,218 range_over, 219 219 buildMoveSingle( stmt ), 220 220 buildMoveOptional( else_ ) -
src/Parser/StatementNode.hpp
rbc07190 r62a38e7 64 64 ForCtrl( StatementNode * stmt, ExpressionNode * condition, ExpressionNode * change ) : 65 65 init( stmt ), condition( condition ), change( change ), range_over( nullptr ) {} 66 ForCtrl( StatementNode * decl, ExpressionNode * range_over, OperKinds kind) :67 init( decl ), condition( nullptr ), change( nullptr ), range_over( range_over ), kind( kind) {}66 ForCtrl( StatementNode * decl, ExpressionNode * _range_over) : 67 init( decl ), condition( nullptr ), change( nullptr ), range_over( _range_over ) {} 68 68 69 69 StatementNode * init; … … 71 71 ExpressionNode * change; 72 72 ExpressionNode * range_over; 73 OperKinds kind;74 73 }; 75 74 -
src/Parser/TypeData.cpp
rbc07190 r62a38e7 1469 1469 ast::ObjectDecl * object = strict_dynamic_cast<ast::ObjectDecl *>( member ); 1470 1470 object->isHidden = ast::EnumDecl::EnumHiding::Hide == ret->hide; 1471 if ( ret->is Opague()&& cur->has_enumeratorValue() ) {1472 SemanticError( td->location, " Opaguecannot have an explicit initializer value." );1471 if ( ret->isTyped && !ret->base && cur->has_enumeratorValue() ) { 1472 SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." ); 1473 1473 } else if ( cur->has_enumeratorValue() ) { 1474 1474 object->init = new ast::SingleInit( -
src/Parser/lex.ll
rbc07190 r62a38e7 10 10 * Created On : Sat Sep 22 08:58:10 2001 11 11 * Last Modified By : Peter A. Buhr 12 * Last Modified On : Thu Jun 2 7 14:38:27202413 * Update Count : 7 8012 * Last Modified On : Thu Jun 20 16:54:05 2024 13 * Update Count : 778 14 14 */ 15 15 … … 458 458 459 459 "@=" { NAMEDOP_RETURN(ATassign); } // CFA 460 "+~" { NAMEDOP_RETURN(ErangeUp); } // CFA461 460 "~=" { NAMEDOP_RETURN(ErangeUpEq); } // CFA 462 "+~=" { NAMEDOP_RETURN(ErangeUpEq); } // CFA463 461 "-~" { NAMEDOP_RETURN(ErangeDown); } // CFA 464 462 "-~=" { NAMEDOP_RETURN(ErangeDownEq); } // CFA -
src/Parser/parser.yy
rbc07190 r62a38e7 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Jun 27 14:45:57202413 // Update Count : 6 70512 // Last Modified On : Mon Jun 24 22:45:20 2024 13 // Update Count : 6684 14 14 // 15 15 … … 224 224 #define UPDOWN( compop, left, right ) (compop == OperKinds::LThan || compop == OperKinds::LEThan ? left : right) 225 225 #define MISSING_ANON_FIELD "illegal syntax, missing loop fields with an anonymous loop index is meaningless as loop index is unavailable in loop body." 226 #define MISSING_LOW "illegal syntax, missing low value for ascanding range so index is uninitialized." 227 #define MISSING_HIGH "illegal syntax, missing high value for descending range so index is uninitialized." 228 229 static ForCtrl * makeForCtrl( const CodeLocation & location, DeclarationNode * init, OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 226 #define MISSING_LOW "illegal syntax, missing low value for up-to range so index is uninitialized." 227 #define MISSING_HIGH "illegal syntax, missing high value for down-to range so index is uninitialized." 228 229 static ForCtrl * makeForCtrl( const CodeLocation & location, DeclarationNode * init, enum OperKinds compop, 230 ExpressionNode * comp, ExpressionNode * inc ) { 230 231 // Wrap both comp/inc if they are non-null. 231 232 if ( comp ) comp = new ExpressionNode( build_binary_val( location, … … 242 243 } 243 244 244 ForCtrl * forCtrl( const CodeLocation & location, DeclarationNode * index, ExpressionNode * start, OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {245 ForCtrl * forCtrl( const CodeLocation & location, DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 245 246 if ( index->initializer ) { 246 247 SemanticError( yylloc, "illegal syntax, direct initialization disallowed. Use instead: type var; initialization ~ comparison ~ increment." ); … … 253 254 } // forCtrl 254 255 255 ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, string * index, ExpressionNode * start, OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {256 ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 256 257 ast::ConstantExpr * constant = dynamic_cast<ast::ConstantExpr *>(type->expr.get()); 257 258 if ( constant && (constant->rep == "0" || constant->rep == "1") ) { … … 267 268 #define MISSING_LOOP_INDEX "illegal syntax, only a single identifier or declaration allowed in initialization, e.g., for ( i; ... ) or for ( int i; ... ). Expression disallowed." 268 269 269 ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, ExpressionNode * index, ExpressionNode * start, OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {270 ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, ExpressionNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 270 271 if ( auto identifier = dynamic_cast<ast::NameExpr *>(index->expr.get()) ) { 271 272 return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc ); 273 // } else if ( auto commaExpr = dynamic_cast<ast::CommaExpr *>( index->expr.get() ) ) { 274 // if ( auto identifier = commaExpr->arg2.as<ast::NameExpr>() ) { 275 // return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc ); 276 // } else { 277 // SemanticError( yylloc, "illegal syntax, loop-index name missing. Expression disallowed." ); return nullptr; 278 // } // if 272 279 } else { 273 280 SemanticError( yylloc, MISSING_LOOP_INDEX ); return nullptr; … … 275 282 } // forCtrl 276 283 277 ForCtrl * enumRangeCtrl( ExpressionNode * index_expr, __attribute__((unused)) OperKinds compop,ExpressionNode * range_over_expr ) {284 ForCtrl * enumRangeCtrl( ExpressionNode * index_expr, ExpressionNode * range_over_expr ) { 278 285 if ( auto identifier = dynamic_cast<ast::NameExpr *>(index_expr->expr.get()) ) { 279 286 DeclarationNode * indexDecl = DeclarationNode::newName( new std::string(identifier->name) ); 280 287 assert( range_over_expr ); 281 return new ForCtrl( new StatementNode( indexDecl ), range_over_expr, compop ); 288 return new ForCtrl( new StatementNode( indexDecl ), range_over_expr ); 289 // } else if (auto commaExpr = dynamic_cast<ast::CommaExpr *>( index_expr->expr.get() )) { 290 // if ( auto identifier = commaExpr->arg1.as<ast::NameExpr>() ) { 291 // assert( range_over_expr ); 292 // DeclarationNode * indexDecl = distAttr( 293 // DeclarationNode::newTypeof( range_over_expr, true ), 294 // DeclarationNode::newName( new std::string( identifier->name) ) ); 295 // return new ForCtrl( new StatementNode( indexDecl ), range_over_expr ); 296 // } else { 297 // SemanticError( yylloc, "illegal syntax, loop-index name missing. Comma expression disallowed." ); return nullptr; 298 // } // if 282 299 } else { 283 300 SemanticError( yylloc, MISSING_LOOP_INDEX ); return nullptr; … … 409 426 %token ANDassign ERassign ORassign // &= ^= |= 410 427 411 %token ErangeUp ErangeUpEq ErangeDown ErangeDownEq // +~ +~=/~= -~ -~=428 %token ErangeUpEq ErangeDown ErangeDownEq // ~= -~ -~= 412 429 %token ATassign // @= 413 430 … … 1505 1522 { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; } 1506 1523 1507 // These rules accept a comma_expression for the initialization, when only an identifier is correct. Being1508 // permissive allows for a better error message from forCtrl.1509 1524 | comma_expression ';' comma_expression // CFA 1510 1525 { $$ = forCtrl( yylloc, $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); } … … 1526 1541 } 1527 1542 | comma_expression ';' '@' updowneq '@' // CFA, invalid syntax rule 1528 { SemanticError( yylloc, "illegal syntax, missing low/high value for ascending/descendingrange so index is uninitialized." ); $$ = nullptr; }1543 { SemanticError( yylloc, "illegal syntax, missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; } 1529 1544 1530 1545 | comma_expression ';' comma_expression updowneq comma_expression '~' comma_expression // CFA … … 1555 1570 } 1556 1571 | comma_expression ';' '@' updowneq '@' '~' '@' // CFA 1557 { SemanticError( yylloc, "illegal syntax, missing low/high value for ascending/descendingrange so index is uninitialized." ); $$ = nullptr; }1572 { SemanticError( yylloc, "illegal syntax, missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; } 1558 1573 1559 1574 | declaration comma_expression // CFA … … 1603 1618 } 1604 1619 | declaration '@' updowneq '@' '~' '@' // CFA, invalid syntax rule 1605 { SemanticError( yylloc, "illegal syntax, missing low/high value for ascending/descendingrange so index is uninitialized." ); $$ = nullptr; }1620 { SemanticError( yylloc, "illegal syntax, missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; } 1606 1621 1607 1622 | comma_expression ';' enum_key // CFA, enum type 1608 1623 { 1609 $$ = enumRangeCtrl( $1, OperKinds::LEThan,new ExpressionNode( new ast::TypeExpr( yylloc, $3->buildType() ) ) );1624 $$ = enumRangeCtrl( $1, new ExpressionNode( new ast::TypeExpr( yylloc, $3->buildType() ) ) ); 1610 1625 } 1611 1626 | comma_expression ';' downupdowneq enum_key // CFA, enum type, reverse direction 1612 1627 { 1613 if ( $3 == OperKinds::GThan ) { 1614 SemanticError( yylloc, "all enumeration ranges are equal (all values). Add an equal, e.g., ~=, -~=." ); $$ = nullptr; 1615 $3 = OperKinds::GEThan; 1616 } // if 1617 $$ = enumRangeCtrl( $1, $3, new ExpressionNode( new ast::TypeExpr( yylloc, $4->buildType() ) ) ); 1628 if ( $3 == OperKinds::LEThan || $3 == OperKinds::GEThan ) { 1629 SemanticError( yylloc, "illegal syntax, all enumeration ranges are equal (all values). Remove \"=~\"." ); $$ = nullptr; 1630 } 1631 SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr; 1618 1632 } 1619 1633 ; … … 1628 1642 ; 1629 1643 1630 // This rule exists to handle the ambiguity with unary operator '~'. The rule is the same as updowneq minus the '~'.1631 // Specifically, "for ( ~5 )" means the complement of 5, not loop 0..4. Hence, in this case "for ( ~= 5 )", i.e., 0..5,1632 // it is not possible to just remove the '='. The entire '~=' must be removed.1633 1644 downupdowneq: 1634 ErangeUp 1635 { $$ = OperKinds::LThan; } 1636 | ErangeDown 1645 ErangeDown 1637 1646 { $$ = OperKinds::GThan; } 1638 1647 | ErangeUpEq … … 1643 1652 1644 1653 updown: 1645 '~' // shorthand 0 ~ 10 => 0 +~ 10 1646 { $$ = OperKinds::LThan; } 1647 | ErangeUp 1654 '~' 1648 1655 { $$ = OperKinds::LThan; } 1649 1656 | ErangeDown -
src/ResolvExpr/CandidateFinder.cpp
rbc07190 r62a38e7 698 698 void postvisit( const ast::CountExpr * countExpr ); 699 699 700 const ast::Expr * makeEnumOffsetCast( const ast::EnumInstType * src, 701 const ast::EnumInstType * dst 702 , const ast::Expr * expr, Cost minCost ); 703 700 704 void postvisit( const ast::InitExpr * ) { 701 705 assertf( false, "CandidateFinder should never see a resolved InitExpr." ); … … 1209 1213 } 1210 1214 1215 // src is a subset of dst 1216 const ast::Expr * Finder::makeEnumOffsetCast( const ast::EnumInstType * src, 1217 const ast::EnumInstType * dst, 1218 const ast::Expr * expr, 1219 Cost minCost ) { 1220 1221 auto srcDecl = src->base; 1222 auto dstDecl = dst->base; 1223 1224 if (srcDecl->name == dstDecl->name) return expr; 1225 1226 for (auto& dstChild: dstDecl->inlinedDecl) { 1227 Cost c = castCost(src, dstChild, false, symtab, tenv); 1228 ast::CastExpr * castToDst; 1229 if (c<minCost) { 1230 unsigned offset = dstDecl->calChildOffset(dstChild.get()); 1231 if (offset > 0) { 1232 auto untyped = ast::UntypedExpr::createCall( 1233 expr->location, 1234 "?+?", 1235 { new ast::CastExpr( expr, new ast::BasicType(ast::BasicKind::SignedInt) ), 1236 ast::ConstantExpr::from_int(expr->location, offset)}); 1237 CandidateFinder finder(context, tenv); 1238 finder.find( untyped ); 1239 CandidateList winners = findMinCost( finder.candidates ); 1240 CandidateRef & choice = winners.front(); 1241 // choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 1242 choice->expr = new ast::CastExpr(expr->location, choice->expr, dstChild, ast::GeneratedFlag::ExplicitCast); 1243 // castToDst = new ast::CastExpr(choice->expr, dstChild); 1244 castToDst = new ast::CastExpr( 1245 makeEnumOffsetCast( src, dstChild, choice->expr, minCost ), 1246 dst); 1247 1248 } else { 1249 castToDst = new ast::CastExpr( expr, dst ); 1250 } 1251 return castToDst; 1252 } 1253 } 1254 SemanticError(expr, src->base->name + " is not a subtype of " + dst->base->name); 1255 return nullptr; 1256 } 1257 1211 1258 void Finder::postvisit( const ast::CastExpr * castExpr ) { 1212 1259 ast::ptr< ast::Type > toType = castExpr->result; … … 1262 1309 auto argAsEnum = cand->expr->result.as<ast::EnumInstType>(); 1263 1310 auto toAsEnum = toType.as<ast::EnumInstType>(); 1264 if ( argAsEnum && toAsEnum && argAsEnum->name != toAsEnum->name ) { 1265 CandidateFinder subFinder(context, tenv); 1266 ast::ptr<ast::Expr> offsetExpr = subFinder.makeEnumOffsetCast(argAsEnum, toAsEnum, cand->expr, thisCost); 1311 if ( argAsEnum && toAsEnum && argAsEnum->name != toAsEnum->name ) { 1312 ast::ptr<ast::Expr> offsetExpr = makeEnumOffsetCast(argAsEnum, toAsEnum, cand->expr, thisCost); 1267 1313 cand->expr = offsetExpr; 1268 1314 } … … 2147 2193 expr->location, 2148 2194 "?+?", 2149 { new ast::CastExpr( expr->location, 2150 expr, 2151 new ast::BasicType(ast::BasicKind::SignedInt), 2152 ast::GeneratedFlag::ExplicitCast ), 2153 ast::ConstantExpr::from_int(expr->location, offset)} ); 2195 { new ast::CastExpr( expr, new ast::BasicType(ast::BasicKind::SignedInt) ), 2196 ast::ConstantExpr::from_int(expr->location, offset)}); 2154 2197 CandidateFinder finder(context, env); 2155 2198 finder.find( untyped ); -
src/ResolvExpr/CastCost.cpp
rbc07190 r62a38e7 53 53 void postvisit( const ast::EnumInstType * enumInst ) { 54 54 cost = conversionCost( enumInst, dst, srcIsLvalue, symtab, env ); 55 if ( enumInst->base->isTyped() ) {56 auto baseConversionCost =57 castCost( enumInst->base->base, dst, srcIsLvalue, symtab, env );58 cost = baseConversionCost < cost? baseConversionCost: cost;59 }60 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicKind::SignedInt ) };61 Cost intCost = costCalc( integer, dst, srcIsLvalue, symtab, env );62 intCost.incSafe();63 cost = intCost < cost? intCost: cost;64 55 } 65 56 … … 72 63 cost = conversionCost( basicType, dst, srcIsLvalue, symtab, env ); 73 64 if ( Cost::unsafe < cost ) { 74 if ( dynamic_cast<const ast::EnumInstType *>(dst)) { 75 cost = Cost::unsafe; 65 if (auto enumInst = dynamic_cast<const ast::EnumInstType *>(dst)) { 66 // Always explict cast only for typed enum 67 if (enumInst->base->isTyped) cost = Cost::unsafe; 76 68 } 77 69 } … … 82 74 cost = conversionCost( zero, dst, srcIsLvalue, symtab, env ); 83 75 if ( Cost::unsafe < cost ) { 84 if ( dynamic_cast<const ast::EnumInstType *>(dst)) {85 cost = Cost::unsafe;76 if (auto enumInst = dynamic_cast<const ast::EnumInstType *>(dst)) { 77 if (enumInst->base->isTyped) cost = Cost::unsafe; 86 78 } 87 79 } … … 91 83 cost = conversionCost( one, dst, srcIsLvalue, symtab, env ); 92 84 if ( Cost::unsafe < cost ) { 93 if ( dynamic_cast<const ast::EnumInstType *>(dst)) {94 cost = Cost::unsafe;85 if (auto enumInst = dynamic_cast<const ast::EnumInstType *>(dst)) { 86 if (enumInst->base->isTyped) cost = Cost::unsafe; 95 87 } 96 88 } -
src/ResolvExpr/CommonType.cpp
rbc07190 r62a38e7 386 386 } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) { 387 387 const ast::EnumDecl* enumDecl = enumInst->base; 388 if ( !enumDecl-> isCfa) {388 if ( !enumDecl->base ) { 389 389 ast::BasicKind kind = commonTypes[ basic->kind ][ ast::BasicKind::SignedInt ]; 390 390 if ( … … 642 642 const ast::EnumDecl* argDecl = argAsEnumInst->base; 643 643 if (argDecl->isSubTypeOf(paramDecl)) result = param; 644 } else if ( param->base && !param->base->is Cfa) {644 } else if ( param->base && !param->base->isTyped ) { 645 645 auto basicType = new ast::BasicType( ast::BasicKind::UnsignedInt ); 646 646 result = commonType( basicType, type2, tenv, need, have, open, widen); -
src/ResolvExpr/ConversionCost.cpp
rbc07190 r62a38e7 162 162 Cost conversionCost( 163 163 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue, 164 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env164 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env 165 165 ) { 166 166 if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) { … … 235 235 return ast::Pass<ConversionCost>::read( src, dst, srcIsLvalue, symtab, env, conversionCost ); 236 236 } 237 if (const ast::EnumInstType * srcAsInst = dynamic_cast< const ast::EnumInstType * >( src )) {238 if (srcAsInst->base && !srcAsInst->base->isCfa) {239 static const ast::BasicType* integer = new ast::BasicType( ast::BasicKind::UnsignedInt );240 return ast::Pass<ConversionCost>::read( integer, dst, srcIsLvalue, symtab, env, conversionCost );241 }242 }243 237 } else { 244 238 assert( -1 == diff ); 245 239 const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst ); 246 240 assert( dstAsRef ); 247 auto dstBaseType = dstAsRef->base; 248 const ast::Type * newSrc = src; 249 if ( dynamic_cast< const ast::EnumInstType * >( src ) && dstBaseType.as<ast::BasicType>() ) { 250 newSrc = new ast::BasicType( ast::BasicKind::UnsignedInt ); 251 } 252 if ( typesCompatibleIgnoreQualifiers( newSrc, dstAsRef->base, env ) ) { 241 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, env ) ) { 253 242 if ( srcIsLvalue ) { 254 243 if ( src->qualifiers == dstAsRef->base->qualifiers ) { … … 295 284 if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) { 296 285 conversionCostFromBasicToBasic( basicType, dstAsBasic ); 297 } else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {298 if ( dstAsEnumInst->base && !dstAsEnumInst->base->is Cfa) {299 cost = Cost:: safe;286 } else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) { 287 if ( dstAsEnumInst->base && !dstAsEnumInst->base->isTyped ) { 288 cost = Cost::unsafe; 300 289 } 301 290 } … … 377 366 if ( auto dstInst = dynamic_cast<const ast::EnumInstType *>( dst ) ) { 378 367 cost = enumCastCost(inst, dstInst, symtab, env); 379 } else if ( !inst->base->isCfa ) { 380 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicKind::SignedInt ) }; 381 cost = costCalc( integer, dst, srcIsLvalue, symtab, env ); 382 } 383 // cost.incUnsafe(); 368 return; 369 } 370 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicKind::SignedInt ) }; 371 cost = costCalc( integer, dst, srcIsLvalue, symtab, env ); 372 if ( !inst->base->isTyped ) { 373 if ( cost < Cost::unsafe ) { 374 cost.incSafe(); 375 } 376 return; 377 } 378 cost.incUnsafe(); 384 379 } 385 380 … … 459 454 // assuming 0p is supposed to be used for pointers? 460 455 } else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) { 461 if ( dstAsEnumInst->base && !dstAsEnumInst->base->is Cfa) {462 cost = Cost:: safe;456 if ( dstAsEnumInst->base && !dstAsEnumInst->base->isTyped ) { 457 cost = Cost::unsafe; 463 458 } 464 459 } … … 480 475 } 481 476 } else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) { 482 if ( dstAsEnumInst->base && !dstAsEnumInst->base->is Cfa) {483 cost = Cost:: safe;477 if ( dstAsEnumInst->base && !dstAsEnumInst->base->isTyped ) { 478 cost = Cost::unsafe; 484 479 } 485 480 } -
src/ResolvExpr/Unify.cpp
rbc07190 r62a38e7 276 276 void postvisit( const ast::VoidType * ) { 277 277 result = dynamic_cast< const ast::VoidType * >( type2 ); 278 // || tryToUnifyWithEnumValue(vt, type2, tenv, need, have, open, noWiden()); 279 ; 278 280 } 279 281 … … 282 284 result = basic->kind == basic2->kind; 283 285 } 286 // result = result || tryToUnifyWithEnumValue(basic, type2, tenv, need, have, open, noWiden()); 284 287 } 285 288 … … 290 293 noWiden()); 291 294 } 295 // result = result || tryToUnifyWithEnumValue(pointer, type2, tenv, need, have, open, noWiden()); 292 296 } 293 297 … … 308 312 result = unifyExact( 309 313 array->base, array2->base, tenv, need, have, open, noWiden()); 314 // || tryToUnifyWithEnumValue(array, type2, tenv, need, have, open, noWiden()); 310 315 } 311 316 … … 602 607 603 608 result = unifyList( types, types2, tenv, need, have, open ); 609 // || tryToUnifyWithEnumValue(tuple, type2, tenv, need, have, open, noWiden()); 604 610 } 605 611 606 612 void postvisit( const ast::VarArgsType * ) { 607 613 result = dynamic_cast< const ast::VarArgsType * >( type2 ); 614 // || tryToUnifyWithEnumValue(vat, type2, tenv, need, have, open, noWiden()); 608 615 } 609 616 610 617 void postvisit( const ast::ZeroType * ) { 611 618 result = dynamic_cast< const ast::ZeroType * >( type2 ); 619 // || tryToUnifyWithEnumValue(zt, type2, tenv, need, have, open, noWiden()); 612 620 } 613 621 614 622 void postvisit( const ast::OneType * ) { 615 623 result = dynamic_cast< const ast::OneType * >( type2 ); 624 // || tryToUnifyWithEnumValue(ot, type2, tenv, need, have, open, noWiden()); 616 625 } 617 626 }; -
src/Validate/ImplementEnumFunc.cpp
rbc07190 r62a38e7 476 476 477 477 void ImplementEnumFunc::previsit(const ast::EnumDecl* enumDecl) { 478 if (!enumDecl->body || !enumDecl->is Cfa) return;478 if (!enumDecl->body || !enumDecl->isTyped) return; 479 479 ast::EnumInstType enumInst(enumDecl->name); 480 480 enumInst.base = enumDecl;
Note:
See TracChangeset
for help on using the changeset viewer.