Changes in / [0188539c:42cdd07d]
- Files:
-
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/prelude/builtins.c
r0188539c r42cdd07d 178 178 } // distribution 179 179 180 struct quasi_void {}; 181 static inline void ?{}(quasi_void &) {} 182 static inline void ?{}(quasi_void &, quasi_void) {} 183 static inline void ^?{}(quasi_void &) {} 184 static inline quasi_void ?=?(quasi_void &, quasi_void & _src) { return _src; } 185 180 186 // Local Variables: // 181 187 // mode: c // -
libcfa/src/enum.cfa
r0188539c r42cdd07d 1 1 #include "enum.hfa" 2 #include "fstream.hfa" 2 3 3 4 #pragma GCC visibility push(default) 4 5 5 forall(T, E| TypedEnum(T, E)) { 6 // constructors 6 forall(ostype & | basic_ostream(ostype), E, V| CfaEnum(E, V)) 7 ostype & ?|?(ostype& os, E e) { 8 return os | type_name(e) | "." | labelE(e); 9 } 7 10 8 // comparison 9 int ?==?(E l, E r) { return posE(l) == posE(r); } 10 int ?!=?(E l, E r) { return posE(l) != posE(r); } 11 int ?!=?(E l, zero_t) { return !( posE(l) == 0 ); } 12 int ?<?(E l, E r) { return posE(l) < posE(r); } 13 int ?<=?(E l, E r) { return posE(l) <= posE(r); } 14 int ?>?(E l, E r) { return posE(l) > posE(r); } 15 int ?>=?(E l, E r) { return posE(l) >= posE(r); } 11 forall(ostype & | basic_ostream(ostype), E| CfaEnum(E, quasi_void)) 12 ostype & ?|?(ostype& os, E e) { 13 return os | type_name(e) | "." | labelE(e); 16 14 } -
libcfa/src/enum.hfa
r0188539c r42cdd07d 1 1 #pragma once 2 2 3 forall(T) { // T is the based type of enum(T) 4 forall(E) trait Bounded { 5 E lowerBound(); 6 E upperBound(); 7 }; 3 #include "iostream.hfa" 8 4 9 forall(E| Bounded(T, E)) trait Serial { 10 unsigned fromInstance(E e); 11 E fromInt(unsigned i); 12 E succ(E e); 13 E pred(E e); 14 }; 5 forall(E) trait Bounded { 6 E lowerBound(); 7 E upperBound(); 8 }; 15 9 16 // Opague Enum + TypedEnum 17 forall(E | Serial(T, E)) trait CfaEnum { 18 char * labelE(E e); 19 unsigned int posE(E e); 20 }; 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 }; 21 16 22 forall(E| CfaEnum(T, E)) trait TypedEnum { 23 T valueE(E e); 24 }; 17 // Design one 18 forall(E, V | Serial(E)) trait CfaEnum { 19 char* labelE(E e); 20 unsigned int posE(E e); 21 V valueE(E e); 22 char* type_name(E e); 23 }; 25 24 26 forall(E | TypedEnum(T, E)) { 27 // comparison 28 int ?==?(E l, E r); // true if l and r are same enumerators 29 int ?!=?(E l, E r); // true if l and r are different enumerators 30 int ?!=?(E l, zero_t); // true if l is not the first enumerator 31 int ?<?(E l, E r); // true if l is an enuemerator before r 32 int ?<=?(E l, E r); // true if l before or the same as r 33 int ?>?(E l, E r); // true if l is an enuemrator after r 34 int ?>=?(E l, E r); // true if l after or the same as r 35 } 36 } 25 forall(ostype & | basic_ostream(ostype), E, V| CfaEnum(E, V)) 26 ostype & ?|?(ostype&, E); 27 28 forall(ostype & | basic_ostream(ostype), E| CfaEnum(E, quasi_void)) 29 ostype & ?|?(ostype&, E); 30 31 // Design two <- should go for this if we have change the cost model 32 // forall(E | Serial(E)) trait CfaEnum { 33 // char* labelE(E e); 34 // unsigned int posE(E e); 35 // }; 36 37 // forall(E, V| CfaEnum(E)) trait TypedEnum { 38 // V valueE(E e); 39 // }; -
src/AST/Decl.cpp
r0188539c r42cdd07d 170 170 171 171 const std::string EnumDecl::getUnmangeldArrayName( const ast::EnumAttribute attr ) const { 172 switch( attr ) { 173 case ast::EnumAttribute::Value: return "values_" + name ; 174 case ast::EnumAttribute::Label: return "labels_" + name; 175 default: /* Posn does not generate array */ 176 return ""; 172 switch( attr ) { 173 case ast::EnumAttribute::Value: return "values_" + name ; 174 case ast::EnumAttribute::Label: return "labels_" + name; 175 default: /* Posn does not generate array */ 176 return ""; 177 } 178 } 179 180 unsigned EnumDecl::calChildOffset(const std::string & target) const{ 181 unsigned offset = 0; 182 for (auto childEnum: inlinedDecl) { 183 auto childDecl = childEnum->base; 184 if (childDecl->name == target) { 185 return offset; 177 186 } 178 } 187 offset += childDecl->members.size(); 188 } 189 std::cerr << "Cannot find the target enum" << std::endl; 190 return 0; 191 } 192 193 unsigned EnumDecl::calChildOffset(const ast::EnumInstType * target) const{ 194 return calChildOffset(target->base->name); 195 } 196 197 bool EnumDecl::isSubTypeOf(const ast::EnumDecl * other) const { 198 if (name == other->name) return true; 199 for (auto inlined: other->inlinedDecl) { 200 if (isSubTypeOf(inlined->base)) return true; 201 } 202 return false; 203 } 179 204 180 205 } -
src/AST/Decl.hpp
r0188539c r42cdd07d 75 75 bool isDeleted = false; 76 76 bool isTypeFixed = false; 77 bool isHidden = false; 77 78 78 79 DeclWithType( const CodeLocation& loc, const std::string& name, Storage::Classes storage, … … 313 314 ptr<Type> base; 314 315 enum class EnumHiding { Visible, Hide } hide; 316 std::vector< ast::ptr<ast::EnumInstType>> inlinedDecl; // child enums 317 315 318 EnumDecl( const CodeLocation& loc, const std::string& name, bool isTyped = false, 316 319 std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall, … … 328 331 329 332 const std::string getUnmangeldArrayName( const EnumAttribute attr ) const; 333 334 unsigned calChildOffset(const std::string & childEnum) const; 335 unsigned calChildOffset(const ast::EnumInstType * childEnum) const; 336 337 bool isSubTypeOf(const ast::EnumDecl *) const; 330 338 private: 331 339 EnumDecl * clone() const override { return new EnumDecl{ *this }; } -
src/AST/Expr.hpp
r0188539c r42cdd07d 256 256 public: 257 257 ptr<Decl> type_decl; 258 std::string name; 258 const std::string type_name; 259 const std::string name; 259 260 260 261 QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n ) 261 : Expr( loc ), type_decl( d ), name( n ) {} 262 : Expr( loc ), type_decl( d ), type_name(""), name( n ) {} 263 264 QualifiedNameExpr( const CodeLocation & loc, const std::string & type_name, const std::string & name) 265 : Expr( loc ), type_name( type_name ), name( name ) {} 262 266 263 267 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } -
src/AST/Pass.impl.hpp
r0188539c r42cdd07d 560 560 561 561 if ( __visit_children() ) { 562 if ( node->hide == ast::EnumDecl::EnumHiding::Hide ) { 563 guard_symtab guard { *this }; 564 maybe_accept( node, &EnumDecl::base ); 565 maybe_accept( node, &EnumDecl::params ); 566 maybe_accept( node, &EnumDecl::members ); 567 maybe_accept( node, &EnumDecl::attributes ); 568 } else { 569 maybe_accept( node, &EnumDecl::base ); 570 maybe_accept( node, &EnumDecl::params ); 571 maybe_accept( node, &EnumDecl::members ); 572 maybe_accept( node, &EnumDecl::attributes ); 573 } 562 maybe_accept( node, &EnumDecl::base ); 563 maybe_accept( node, &EnumDecl::params ); 564 maybe_accept( node, &EnumDecl::members ); 565 maybe_accept( node, &EnumDecl::attributes ); 566 maybe_accept( node, &EnumDecl::inlinedDecl ); 574 567 } 575 568 -
src/AST/SymbolTable.cpp
r0188539c r42cdd07d 159 159 } 160 160 161 std::vector<SymbolTable::IdData> SymbolTable::lookupIdIgnoreHidden( const std::string &id ) const { 162 std::vector<IdData> out; 163 std::vector<IdData> lookupResult = lookupId(id); 164 for ( auto candidate: lookupResult) { 165 if ( candidate.id ) { 166 if (candidate.id->isHidden) continue; 167 } 168 out.push_back(candidate); 169 } 170 return out; 171 } 172 161 173 std::vector<SymbolTable::IdData> SymbolTable::specialLookupId( SymbolTable::SpecialFunctionKind kind, const std::string & otypeKey ) const { 162 174 static Stats::Counters::CounterGroup * special_stats = Stats::Counters::build<Stats::Counters::CounterGroup>("Special Lookups"); -
src/AST/SymbolTable.hpp
r0188539c r42cdd07d 121 121 /// Gets all declarations with the given ID 122 122 std::vector<IdData> lookupId( const std::string &id ) const; 123 /// Gets all declarations with the given ID, ignoring hidden members from enumeration 124 std::vector<IdData> lookupIdIgnoreHidden( const std::string &id ) const; 123 125 /// Gets special functions associated with a type; if no key is given, returns everything 124 126 std::vector<IdData> specialLookupId( SpecialFunctionKind kind, const std::string & otypeKey = "" ) const; -
src/AST/Util.cpp
r0188539c r42cdd07d 352 352 void previsit( EnumDecl const * decl ) { 353 353 enumDecls.insert( decl ); 354 if ( ast::EnumDecl::EnumHiding::Visible == decl->hide ) { 355 for ( auto & member : decl->members ) { 356 typedDecls.insert( member.strict_as<ast::DeclWithType>() ); 357 } 354 for ( auto & member : decl->members ) { 355 typedDecls.insert( member.strict_as<ast::DeclWithType>() ); 358 356 } 359 357 beginScope(); -
src/GenPoly/Lvalue.cpp
r0188539c r42cdd07d 389 389 assert( 0 == diff ); 390 390 // Remove useless generated casts. 391 if ( expr->isGenerated &&391 if ( expr->isGenerated == ast::GeneratedFlag::GeneratedCast && 392 392 ResolvExpr::typesCompatible( 393 393 expr->result, … … 398 398 std::cerr << "-- " << expr->arg->result << std::endl; 399 399 ) 400 auto argAsEnum = expr->arg.as<ast::EnumInstType>(); 401 auto resultAsEnum = expr->result.as<ast::EnumInstType>(); 402 if (argAsEnum && resultAsEnum) { 403 if (argAsEnum->base->name != resultAsEnum->base->name) { 404 return expr; 405 } 406 } 400 407 return ast::mutate_field( expr->arg.get(), 401 408 &ast::Expr::env, expr->env.get() ); -
src/Parser/TypeData.cpp
r0188539c r42cdd07d 1465 1465 ret->hide = td->aggregate.hiding == EnumHiding::Hide ? ast::EnumDecl::EnumHiding::Hide : ast::EnumDecl::EnumHiding::Visible; 1466 1466 for ( const DeclarationNode * cur = td->aggregate.fields ; cur != nullptr ; cur = cur->next, ++members ) { 1467 if ( cur->enumInLine ) { 1468 // Do Nothing 1469 } else if ( ret->isTyped && !ret->base && cur->has_enumeratorValue() ) { 1467 if (cur->enumInLine) continue; 1468 ast::Decl * member = members->get_and_mutate(); 1469 ast::ObjectDecl * object = strict_dynamic_cast<ast::ObjectDecl *>( member ); 1470 object->isHidden = ast::EnumDecl::EnumHiding::Hide == ret->hide; 1471 if ( ret->isTyped && !ret->base && cur->has_enumeratorValue() ) { 1470 1472 SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." ); 1471 1473 } else if ( cur->has_enumeratorValue() ) { 1472 ast::Decl * member = members->get_and_mutate();1473 ast::ObjectDecl * object = strict_dynamic_cast<ast::ObjectDecl *>( member );1474 1474 object->init = new ast::SingleInit( 1475 1475 td->location, … … 1477 1477 ast::NoConstruct 1478 1478 ); 1479 } else if ( !cur->initializer ) { 1480 if ( baseType && (!dynamic_cast<ast::BasicType *>(baseType) || !dynamic_cast<ast::BasicType *>(baseType)->isInteger())) { 1481 SemanticError( td->location, "Enumerators of an non-integer typed enum must be explicitly initialized." ); 1482 } 1483 } 1479 } 1484 1480 // else cur is a List Initializer and has been set as init in buildList() 1485 1481 // if -
src/Parser/parser.yy
r0188539c r42cdd07d 2827 2827 | enumerator_list ',' visible_hide_opt identifier_or_type_name enumerator_value_opt 2828 2828 { $$ = $1->set_last( DeclarationNode::newEnumValueGeneric( $4, $5 ) ); } 2829 | enumerator_list ',' INLINE type_name enumerator_value_opt2830 { $$ = $1->set_last( DeclarationNode::newEnum ValueGeneric( new string("inline"), nullptr )); }2829 | enumerator_list ',' INLINE type_name 2830 { $$ = $1->set_last( DeclarationNode::newEnumInLine( $4->symbolic.name ) ); } 2831 2831 ; 2832 2832 -
src/ResolvExpr/CandidateFinder.cpp
r0188539c r42cdd07d 513 513 // add new result 514 514 assert( common ); 515 results.emplace_back( 516 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 517 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 518 //} 515 516 auto paramAsEnum = dynamic_cast<const ast::EnumInstType *>(paramType); 517 auto argAsEnum =dynamic_cast<const ast::EnumInstType *>(argType); 518 if (paramAsEnum && argAsEnum) { 519 if (paramAsEnum->base->name != argAsEnum->base->name) { 520 Cost c = castCost(argType, paramType, expr, context.symtab, env); 521 if (c < Cost::infinity) { 522 CandidateFinder subFinder( context, env ); 523 expr = subFinder.makeEnumOffsetCast(argAsEnum, paramAsEnum, expr, c); 524 results.emplace_back( 525 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 526 nextArg + 1, nTuples, expl.cost + c, expl.exprs.size() == 1 ? 0 : 1, j ); 527 continue; 528 } else { 529 std::cerr << "Cannot instantiate " << paramAsEnum->base->name << " with " << argAsEnum->base->name << std::endl; 530 } 531 } 532 } 533 results.emplace_back( 534 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 535 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 519 536 } 520 537 } … … 632 649 const ast::BaseInstType * aggrInst, const ast::Expr * expr, 633 650 const Candidate & cand, const Cost & addedCost, const std::string & name 651 ); 652 653 void addEnumValueAsCandidate(const ast::EnumInstType * instType, const ast::Expr * expr, 654 const Cost & addedCost 634 655 ); 635 656 … … 676 697 void postvisit( const ast::QualifiedNameExpr * qualifiedExpr ); 677 698 699 const ast::Expr * makeEnumOffsetCast( const ast::EnumInstType * src, 700 const ast::EnumInstType * dst 701 , const ast::Expr * expr, Cost minCost ); 702 678 703 void postvisit( const ast::InitExpr * ) { 679 704 assertf( false, "CandidateFinder should never see a resolved InitExpr." ); … … 876 901 } 877 902 903 void Finder::addEnumValueAsCandidate( const ast::EnumInstType * enumInst, const ast::Expr * expr, 904 const Cost & addedCost 905 ) { 906 if ( enumInst->base->base ) { 907 CandidateFinder finder( context, tenv ); 908 auto location = expr->location; 909 auto callExpr = new ast::UntypedExpr( 910 location, new ast::NameExpr( location, "valueE" ), {expr} 911 ); 912 finder.find( callExpr ); 913 CandidateList winners = findMinCost( finder.candidates ); 914 if (winners.size() != 1) { 915 SemanticError( callExpr, "Ambiguous expression in valueE..." ); 916 } 917 CandidateRef & choice = winners.front(); 918 choice->cost += addedCost; 919 addAnonConversions(choice); 920 candidates.emplace_back( std::move(choice) ); 921 } 922 } 923 878 924 /// Adds implicit struct-conversions to the alternative list 879 925 void Finder::addAnonConversions( const CandidateRef & cand ) { … … 894 940 addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" ); 895 941 } else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) { 896 if ( enumInst->base->base ) { 897 CandidateFinder finder( context, tenv ); 898 auto location = aggrExpr->location; 899 auto callExpr = new ast::UntypedExpr( 900 location, new ast::NameExpr( location, "valueE" ), {aggrExpr} 901 ); 902 finder.find( callExpr ); 903 CandidateList winners = findMinCost( finder.candidates ); 904 if (winners.size() != 1) { 905 SemanticError( callExpr, "Ambiguous expression in valueE..." ); 906 } 907 CandidateRef & choice = winners.front(); 908 choice->cost = Cost::unsafe; 909 candidates.emplace_back( std::move(choice) ); 910 } 911 912 } 913 } 942 addEnumValueAsCandidate(enumInst, aggrExpr, Cost::unsafe); 943 } 944 } 945 914 946 915 947 /// Adds aggregate member interpretations … … 1180 1212 } 1181 1213 1214 // src is a subset of dst 1215 const ast::Expr * Finder::makeEnumOffsetCast( const ast::EnumInstType * src, 1216 const ast::EnumInstType * dst, 1217 const ast::Expr * expr, 1218 Cost minCost ) { 1219 1220 auto srcDecl = src->base; 1221 auto dstDecl = dst->base; 1222 1223 if (srcDecl->name == dstDecl->name) return expr; 1224 1225 for (auto& dstChild: dstDecl->inlinedDecl) { 1226 Cost c = castCost(src, dstChild, false, symtab, tenv); 1227 ast::CastExpr * castToDst; 1228 if (c<minCost) { 1229 unsigned offset = dstDecl->calChildOffset(dstChild.get()); 1230 if (offset > 0) { 1231 auto untyped = ast::UntypedExpr::createCall( 1232 expr->location, 1233 "?+?", 1234 { new ast::CastExpr( expr, new ast::BasicType(ast::BasicKind::SignedInt) ), 1235 ast::ConstantExpr::from_int(expr->location, offset)}); 1236 CandidateFinder finder(context, tenv); 1237 finder.find( untyped ); 1238 CandidateList winners = findMinCost( finder.candidates ); 1239 CandidateRef & choice = winners.front(); 1240 // choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 1241 choice->expr = new ast::CastExpr(expr->location, choice->expr, dstChild, ast::GeneratedFlag::ExplicitCast); 1242 // castToDst = new ast::CastExpr(choice->expr, dstChild); 1243 castToDst = new ast::CastExpr( 1244 makeEnumOffsetCast( src, dstChild, choice->expr, minCost ), 1245 dst); 1246 1247 } else { 1248 castToDst = new ast::CastExpr( expr, dst ); 1249 } 1250 return castToDst; 1251 } 1252 } 1253 SemanticError(expr, src->base->name + " is not a subtype of " + dst->base->name); 1254 return nullptr; 1255 } 1256 1182 1257 void Finder::postvisit( const ast::CastExpr * castExpr ) { 1183 1258 ast::ptr< ast::Type > toType = castExpr->result; … … 1229 1304 ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ) 1230 1305 : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ); 1306 1307 // Redefine enum cast 1308 auto argAsEnum = cand->expr->result.as<ast::EnumInstType>(); 1309 auto toAsEnum = toType.as<ast::EnumInstType>(); 1310 if ( argAsEnum && toAsEnum && argAsEnum->name != toAsEnum->name ) { 1311 ast::ptr<ast::Expr> offsetExpr = makeEnumOffsetCast(argAsEnum, toAsEnum, cand->expr, thisCost); 1312 cand->expr = offsetExpr; 1313 } 1231 1314 1232 1315 PRINT( … … 1246 1329 minCastCost = thisCost; 1247 1330 matches.clear(); 1248 1249 1250 } 1251 // ambiguous case, still output candidates to print in error message 1331 } 1332 // ambigious case, still output candidates to print in error message 1252 1333 if ( cand->cost == minExprCost && thisCost == minCastCost ) { 1253 1334 CandidateRef newCand = std::make_shared<Candidate>( … … 1264 1345 } 1265 1346 candidates = std::move(matches); 1266 1267 1347 //CandidateList minArgCost = findMinCost( matches ); 1268 1348 //promoteCvtCost( minArgCost ); … … 1374 1454 } 1375 1455 } else { 1376 declList = symtab.lookupId ( nameExpr->name );1456 declList = symtab.lookupIdIgnoreHidden( nameExpr->name ); 1377 1457 } 1378 1458 PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; ) … … 1386 1466 ast::Expr * newExpr = data.combine( nameExpr->location, cost ); 1387 1467 1388 // bool bentConversion = false;1389 // if ( auto inst = newExpr->result.as<ast::EnumInstType>() ) {1390 // if ( inst->base && inst->base->base ) {1391 // bentConversion = true;1392 // }1393 // }1394 1395 // CandidateRef newCand = std::make_shared<Candidate>(1396 // newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, bentConversion? Cost::safe: Cost::zero,1397 // cost );1398 1468 CandidateRef newCand = std::make_shared<Candidate>( 1399 1469 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, … … 1813 1883 if ( const ast::EnumInstType * enumInstType = 1814 1884 dynamic_cast<const ast::EnumInstType *>( t ) ) { 1815 if ( enumInstType->base->name == expr->type_decl->name ) { 1885 if ( (enumInstType->base->name == expr->type_name) 1886 || (expr->type_decl && enumInstType->base->name == expr->type_decl->name) ) { 1816 1887 Cost cost = Cost::zero; 1817 1888 ast::Expr * newExpr = data.combine( expr->location, cost ); 1818 // CandidateRef newCand =1819 // std::make_shared<Candidate>(1820 // newExpr, copy( tenv ), ast::OpenVarSet{},1821 // ast::AssertionSet{}, Cost::safe, cost1822 // );1823 1889 CandidateRef newCand = 1824 1890 std::make_shared<Candidate>( … … 2096 2162 2097 2163 return expr; 2164 } 2165 2166 const ast::Expr * CandidateFinder::makeEnumOffsetCast( const ast::EnumInstType * src, 2167 const ast::EnumInstType * dst, 2168 const ast::Expr * expr, 2169 Cost minCost ) { 2170 2171 auto srcDecl = src->base; 2172 auto dstDecl = dst->base; 2173 2174 if (srcDecl->name == dstDecl->name) return expr; 2175 2176 for (auto& dstChild: dstDecl->inlinedDecl) { 2177 Cost c = castCost(src, dstChild, false, context.symtab, env); 2178 ast::CastExpr * castToDst; 2179 if (c<minCost) { 2180 unsigned offset = dstDecl->calChildOffset(dstChild.get()); 2181 if (offset > 0) { 2182 auto untyped = ast::UntypedExpr::createCall( 2183 expr->location, 2184 "?+?", 2185 { new ast::CastExpr( expr, new ast::BasicType(ast::BasicKind::SignedInt) ), 2186 ast::ConstantExpr::from_int(expr->location, offset)}); 2187 CandidateFinder finder(context, env); 2188 finder.find( untyped ); 2189 CandidateList winners = findMinCost( finder.candidates ); 2190 CandidateRef & choice = winners.front(); 2191 choice->expr = new ast::CastExpr(expr->location, choice->expr, dstChild, ast::GeneratedFlag::ExplicitCast); 2192 castToDst = new ast::CastExpr( 2193 makeEnumOffsetCast( src, dstChild, choice->expr, minCost ), 2194 dst); 2195 } else { 2196 castToDst = new ast::CastExpr( expr, dst ); 2197 } 2198 return castToDst; 2199 } 2200 } 2201 SemanticError(expr, src->base->name + " is not a subtype of " + dst->base->name); 2202 return nullptr; 2098 2203 } 2099 2204 -
src/ResolvExpr/CandidateFinder.hpp
r0188539c r42cdd07d 58 58 iterator end() { return candidates.end(); } 59 59 const_iterator end() const { return candidates.end(); } 60 61 const ast::Expr * makeEnumOffsetCast( const ast::EnumInstType * src, 62 const ast::EnumInstType * dst, const ast::Expr * expr, Cost minCost ); 60 63 }; 61 64 -
src/ResolvExpr/CastCost.cpp
r0188539c r42cdd07d 36 36 namespace ResolvExpr { 37 37 38 Cost castCost( 39 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue, 40 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env 41 ); 42 38 43 namespace { 39 44 struct CastCost : public ConversionCost { … … 45 50 const ast::TypeEnvironment & env, CostCalculation costFunc ) 46 51 : ConversionCost( dst, srcIsLvalue, symtab, env, costFunc ) {} 52 53 void postvisit( const ast::EnumInstType * enumInst ) { 54 cost = conversionCost( enumInst, dst, srcIsLvalue, symtab, env ); 55 } 47 56 48 57 void postvisit( const ast::BasicType * basicType ) { … … 104 113 cost = Cost::unsafe; 105 114 } 106 }107 }108 109 void postvist( const ast::EnumInstType * ) {110 if ( auto basic = dynamic_cast< const ast::BasicType * >(dst) ) {111 if ( basic->isInteger() ) cost = Cost::unsafe;112 115 } 113 116 } -
src/ResolvExpr/CommonType.cpp
r0188539c r42cdd07d 636 636 void postvisit( const ast::UnionInstType * ) {} 637 637 638 void postvisit( const ast::EnumInstType * enumInst ) { 639 if ( enumInst->base && !enumInst->base->isTyped ) { 638 void postvisit( const ast::EnumInstType * param ) { 639 auto argAsEnumInst = dynamic_cast<const ast::EnumInstType *>(type2); 640 if ( argAsEnumInst ) { 641 const ast::EnumDecl* paramDecl = param->base; 642 const ast::EnumDecl* argDecl = argAsEnumInst->base; 643 if (argDecl->isSubTypeOf(paramDecl)) result = param; 644 } else if ( param->base && !param->base->isTyped ) { 640 645 auto basicType = new ast::BasicType( ast::BasicKind::UnsignedInt ); 641 646 result = commonType( basicType, type2, tenv, need, have, open, widen); -
src/ResolvExpr/ConversionCost.cpp
r0188539c r42cdd07d 191 191 } 192 192 193 Cost enumCastCost ( 194 const ast::EnumInstType * src, const ast::EnumInstType * dst, 195 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env 196 ); 197 193 198 static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue, 194 199 int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, … … 359 364 360 365 void ConversionCost::postvisit( const ast::EnumInstType * inst ) { 361 if ( auto dstAsInst = dynamic_cast<const ast::EnumInstType *>( dst ) ) { 362 if (inst->base && dstAsInst->base) { 363 if (inst->base->name == dstAsInst->base->name) { 364 cost = Cost::zero; 365 return; 366 } 367 } 366 if ( auto dstInst = dynamic_cast<const ast::EnumInstType *>( dst ) ) { 367 cost = enumCastCost(inst, dstInst, symtab, env); 368 368 return; 369 369 } … … 481 481 } 482 482 483 // (dst) src is safe is src is a subtype of dst, or dst {inline src, ...} 484 Cost enumCastCost ( 485 const ast::EnumInstType * src, const ast::EnumInstType * dst, 486 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env 487 ) { 488 auto srcDecl = src->base; 489 auto dstDecl = dst->base; 490 if (srcDecl->name == dstDecl->name) return Cost::safe; 491 Cost minCost = Cost::infinity; 492 for (auto child: dstDecl->inlinedDecl) { 493 Cost c = enumCastCost(src, child, symtab, env) + Cost::safe; 494 if (c<minCost) minCost = c; 495 } 496 return minCost; 497 } 498 499 483 500 // size_t ConversionCost::traceId = Stats::Heap::new_stacktrace_id("ConversionCost"); 484 501 -
src/ResolvExpr/Resolver.cpp
r0188539c r42cdd07d 201 201 && typesCompatible( castExpr->arg->result, castExpr->result ) 202 202 ) { 203 auto argAsEnum = castExpr->arg.as<ast::EnumInstType>(); 204 auto resultAsEnum = castExpr->result.as<ast::EnumInstType>(); 205 if (argAsEnum && resultAsEnum) { 206 if (argAsEnum->base->name != resultAsEnum->base->name) { 207 std::cerr << "Enum Cast: " << argAsEnum->base->name << " to " << resultAsEnum->base->name << std::endl; 208 return castExpr; 209 } 210 } 203 211 // generated cast is the same type as its argument, remove it after keeping env 204 212 return ast::mutate_field( -
src/Validate/Autogen.cpp
r0188539c r42cdd07d 410 410 } 411 411 412 /// Use the current type T to create `T ? {}(T & _dst, T _src)`.412 /// Use the current type T to create `T ?=?(T & _dst, T _src)`. 413 413 ast::FunctionDecl * FuncGenerator::genAssignProto() const { 414 414 // Only the name is different, so just reuse the generation function. -
src/Validate/EnumAndPointerDecay.cpp
r0188539c r42cdd07d 47 47 new ast::EnumInstType( decl, ast::CV::Const ) ) ); 48 48 } else if ( auto value = member.as<ast::InlineMemberDecl>() ) { 49 if ( auto targetEnum = symtab.lookupEnum( value->name ) ) { 50 for ( auto enumMember : targetEnum->members ) { 51 auto enumObject = enumMember.strict_as<ast::ObjectDecl>(); 52 buffer.push_back( new ast::ObjectDecl( 53 // Get the location from the "inline" declaration. 54 value->location, 55 enumObject->name, 56 // Construct a new EnumInstType as the type. 57 new ast::EnumInstType( decl, ast::CV::Const ), 58 enumObject->init, 59 enumObject->storage, 60 enumObject->linkage, 61 enumObject->bitfieldWidth, 62 {}, 63 enumObject->funcSpec 64 ) ); 65 } 49 auto targetEnum = symtab.lookupEnum( value->name ); 50 // assert( targetEnum ); 51 if (!targetEnum) { 52 SemanticError(value, "Only another enum is allowed for enum inline syntax "); 53 } 54 const ast::EnumInstType * instType = new ast::EnumInstType(targetEnum); 55 mut->inlinedDecl.push_back( std::move(instType) ); 56 for ( auto enumMember : targetEnum->members ) { 57 auto enumObject = enumMember.strict_as<ast::ObjectDecl>(); 58 buffer.push_back(new ast::ObjectDecl( 59 // Get the location from the "inline" declaration. 60 value->location, 61 enumObject->name, 62 // Construct a new EnumInstType as the type. 63 new ast::EnumInstType( decl, ast::CV::Const ), 64 enumObject->init, 65 enumObject->storage, 66 enumObject->linkage, 67 enumObject->bitfieldWidth, 68 {}, 69 enumObject->funcSpec 70 )); 66 71 } 67 72 } -
src/Validate/ImplementEnumFunc.cpp
r0188539c r42cdd07d 10 10 const ast::EnumDecl* decl; 11 11 unsigned int functionNesting; 12 const ast::StructDecl* quasi_void_decl; 12 13 ast::Linkage::Spec proto_linkage; 13 14 … … 24 25 : decl(decl), 25 26 functionNesting{functionNesting}, 27 quasi_void_decl(new ast::StructDecl(decl->location, 28 "quasi_void", ast::AggregateDecl::Struct, 29 {}, ast::Linkage::AutoGen)), 26 30 proto_linkage{ast::Linkage::Cforall} {} 27 31 … … 52 56 void genSuccPredBody(ast::FunctionDecl *, const char *) const; 53 57 58 void genTypeNameFunc(); 59 54 60 // Implement TypedEnum trait 55 61 void genTypedEnumFuncs(); … … 58 64 ast::FunctionDecl* genLabelProto() const; 59 65 ast::FunctionDecl* genValueProto() const; 66 ast::FunctionDecl* genQuasiValueProto() const; 67 ast::FunctionDecl* genTypeNameProto() const; 68 60 69 void genValueOrLabelBody( 61 70 ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const; 62 71 void genPosnBody(ast::FunctionDecl* func) const; 63 64 //////////////// 65 66 // --------------------------------------------------- 67 // ast::FunctionDecl* genAttrCtorProto() const; 68 /// Changes the node inside a pointer so that it has the unused attribute. 69 void addUnusedAttribute(ast::ptr<ast::DeclWithType>& declPtr) { 70 ast::DeclWithType* decl = declPtr.get_and_mutate(); 71 decl->attributes.push_back(new ast::Attribute("unused")); 72 } 72 void genQuasiValueBody(ast::FunctionDecl* func) const; 73 void genTypeNameBody(ast::FunctionDecl* func) const; 73 74 74 75 // ---------------------------------------------------- … … 117 118 return inits; 118 119 } 120 119 121 const ast::Init* EnumAttrFuncGenerator::getAutoInit( 120 122 const ast::Init* prev) const { … … 189 191 190 192 ast::FunctionDecl* EnumAttrFuncGenerator::genValueProto() const { 193 if (decl->base) 194 return genProto( 195 "valueE", 196 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))}, 197 {new ast::ObjectDecl(getLocation(), "_ret", 198 ast::deepCopy(decl->base))}); 199 else 200 return genQuasiValueProto(); 201 } 202 203 ast::FunctionDecl* EnumAttrFuncGenerator::genQuasiValueProto() const { 191 204 return genProto( 192 205 "valueE", 193 206 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))}, 194 207 {new ast::ObjectDecl(getLocation(), "_ret", 195 ast::deepCopy(decl->base))});208 new ast::StructInstType(quasi_void_decl))}); 196 209 } 197 210 … … 210 223 {new ast::ObjectDecl(getLocation(), "_ret", new ast::BasicType(ast::BasicKind::UnsignedInt))} 211 224 ); 225 } 226 227 ast::FunctionDecl* EnumAttrFuncGenerator::genTypeNameProto() const { 228 return genProto( 229 "type_name", 230 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))}, 231 {new ast::ObjectDecl( 232 getLocation(), "_ret", 233 new ast::PointerType(new ast::BasicType{ast::BasicKind::Char}))}); 212 234 } 213 235 … … 268 290 ); 269 291 } 270 271 292 272 293 void EnumAttrFuncGenerator::genSerialTraitFuncs() { … … 302 323 const CodeLocation & loc = func->location; 303 324 auto mem = func->name=="lowerBound"? decl->members.front() : decl->members.back(); 304 auto expr = new ast::NameExpr( loc, mem->name ); 325 // auto expr = new ast::NameExpr( loc, mem->name ); 326 auto expr = new ast::QualifiedNameExpr( loc, decl->name, mem->name ); 305 327 func->stmts = new ast::CompoundStmt( loc, {new ast::ReturnStmt(loc, expr)}); 306 328 } … … 349 371 } 350 372 373 void EnumAttrFuncGenerator::genQuasiValueBody(ast::FunctionDecl* func) const { 374 auto location = func->location; 375 const ast::ObjectDecl * objDecl = new ast::ObjectDecl( 376 location, "_out", new ast::StructInstType( quasi_void_decl )); 377 const ast::DeclStmt * declStmt = new ast::DeclStmt(location, objDecl); 378 const ast::VariableExpr * varExpr = new ast::VariableExpr(location, objDecl); 379 const ast::ReturnStmt * retStmt = new ast::ReturnStmt(location, varExpr); 380 381 func->stmts = new ast::CompoundStmt( 382 location, {declStmt, retStmt} 383 ); 384 } 385 351 386 void EnumAttrFuncGenerator::genPosnBody(ast::FunctionDecl* func) const { 352 387 auto castExpr = new ast::CastExpr( … … 359 394 } 360 395 396 void EnumAttrFuncGenerator::genTypeNameBody(ast::FunctionDecl* func) const { 397 const ast::Expr * type_name = ast::ConstantExpr::from_string(func->location, decl->name); 398 func->stmts = new ast::CompoundStmt( 399 func->location, {new ast::ReturnStmt(func->location, type_name)} 400 ); 401 } 402 361 403 void EnumAttrFuncGenerator::genTypedEnumFunction(const ast::EnumAttribute attr) { 362 if (attr == ast::EnumAttribute::Value || 363 attr == ast::EnumAttribute::Label) { 364 // TypedEnum's backing arrays 365 std::vector<ast::ptr<ast::Init>> inits = 366 attr == ast::EnumAttribute::Value ? genValueInit() : genLabelInit(); 404 if (attr == ast::EnumAttribute::Value) { 405 if (decl->base) { 406 // TypedEnum's backing arrays 407 std::vector<ast::ptr<ast::Init>> inits = genValueInit(); 408 ast::ObjectDecl* arrayProto = 409 genAttrArrayProto(attr, getLocation(), inits); 410 forwards.push_back(arrayProto); 411 412 ast::FunctionDecl* funcProto = genValueProto(); 413 produceForwardDecl(funcProto); 414 genValueOrLabelBody(funcProto, arrayProto); 415 produceDecl(funcProto); 416 } else { 417 ast::FunctionDecl* funcProto = genQuasiValueProto(); 418 produceForwardDecl(funcProto); 419 genQuasiValueBody(funcProto); 420 produceDecl(funcProto); 421 } 422 } else if (attr == ast::EnumAttribute::Label) { 423 std::vector<ast::ptr<ast::Init>> inits = genLabelInit(); 367 424 ast::ObjectDecl* arrayProto = 368 425 genAttrArrayProto(attr, getLocation(), inits); 369 426 forwards.push_back(arrayProto); 370 371 ast::FunctionDecl* funcProto = ( attr == ast::EnumAttribute::Value ) 372 ? genValueProto() 373 : genLabelProto(); 427 ast::FunctionDecl* funcProto = genLabelProto(); 374 428 produceForwardDecl(funcProto); 375 429 genValueOrLabelBody(funcProto, arrayProto); … … 384 438 385 439 void EnumAttrFuncGenerator::genTypedEnumFuncs() { 386 if (decl->base)genTypedEnumFunction(ast::EnumAttribute::Value);440 genTypedEnumFunction(ast::EnumAttribute::Value); 387 441 genTypedEnumFunction(ast::EnumAttribute::Label); 388 442 genTypedEnumFunction(ast::EnumAttribute::Posn); 443 } 444 445 void EnumAttrFuncGenerator::genTypeNameFunc() { 446 ast::FunctionDecl* funcProto = genTypeNameProto(); 447 produceForwardDecl(funcProto); 448 genTypeNameBody(funcProto); 449 produceDecl(funcProto); 389 450 } 390 451 … … 392 453 std::list<ast::ptr<ast::Decl>>& decls) { 393 454 // Generate the functions (they go into forwards and definitions). 455 genTypeNameFunc(); 394 456 genTypedEnumFuncs(); 395 457 genSerialTraitFuncs(); -
tests/enum_tests/.expect/enumInlineValue.txt
r0188539c r42cdd07d 1 enumB.A is 5 2 enumB.B is 6 3 enumB.D is 11 4 enumB.E is 12 1 Symbols (enumerator) should have the same values: 2 Symbol a: (10) 10, 10, 10 3 Symbol b: (20) 20, 20 4 Symbol ab: (30) 30 5 Symbol c: (40) 40, 40, 40 6 Symbol d: (50) 50, 50, 50 7 Symbol cd: (60) 60, 60 8 Symbol acd: (70) 70 9 Casting/Upcasting: 10 Symbol a: (10) 10, 10, 10 11 Symbol b: (20) 20, 20 12 Symbol ab: (30) 30 13 Symbol c: (40) 40, 40, 40, 40, 40 14 Symbol d: (50) 50, 50, 50, 50 15 Symbol cd: (60) 60, 60 16 Symbol acd: (70) 70 17 Function Call: 18 Symbol a: (10) 10, 10 19 Symbol c: (40) 40, 40 20 Symbol d: (50) 50, 50 21 Symbol cd: (60) 60, 60 22 Symbol acd: (70) 70 -
tests/enum_tests/enumInlineValue.cfa
r0188539c r42cdd07d 1 1 #include <fstream.hfa> 2 enum enumA { 3 A=5, B, C=10, D 2 #include <enum.hfa> 3 4 enum(int) A !{ 5 a = 10 4 6 }; 5 7 6 enum enumB { 7 inline enumA, 8 E 8 enum(int) B { 9 b = 20 9 10 }; 10 11 12 enum(int) AB { 13 inline A, 14 inline B, 15 ab = 30 16 }; 17 18 enum(int) C { 19 c = 40 20 }; 21 22 enum(int) D { 23 d = 50 24 }; 25 26 enum(int) CD { 27 inline C, 28 inline D, 29 cd = 60 30 }; 31 32 enum(int) ACD { 33 inline A, 34 inline CD, 35 acd = 70 36 }; 37 38 // Note: variable name (cat in this case) cannot be overloaded with those declared in enum, 39 // Probably for the same reason as const overloading problem 40 // i.e. int identity_t(enum ACD a) would not work as the valueE(a) is ambigious currently 41 int identity_t(enum ACD cat) { 42 return valueE(cat); 43 } 44 11 45 int main() { 12 enum enumB val = A; 13 sout | "enumB.A is" | val; 14 enum enumB val2 = enumB.B; 15 sout | "enumB.B is" | val2; 16 sout | "enumB.D is" | enumB.D; 17 sout | "enumB.E is" | enumB.E; 46 // Note: We need to use qualified name syntax even if no ! hidding 47 // Because Inline introduce ambiguity on symbols 48 sout | "Symbols (enumerator) should have the same values:" |nl; 49 sout | "Symbol a: (10) " | valueE(A.a) | "," | valueE(AB.a) | "," | valueE(ACD.a) | nl; 50 sout | "Symbol b: (20) " | valueE(B.b) | "," | valueE(AB.b) | nl; 51 sout | "Symbol ab: (30) " | valueE(AB.ab) | nl; 52 sout | "Symbol c: (40) " | valueE(C.c) | "," | valueE(CD.c) | "," | valueE(ACD.c) | nl; 53 sout | "Symbol d: (50) " | valueE(D.d) | "," | valueE(CD.d) | "," | valueE(ACD.d) | nl; 54 sout | "Symbol cd: (60) " | valueE(CD.cd) | "," | valueE(ACD.cd) | nl; 55 sout | "Symbol acd: (70) " | valueE(ACD.acd) | nl; 56 57 sout | "Casting/Upcasting:" | nl; 58 sout | "Symbol a: (10) " | valueE((A)A.a) | "," | valueE((AB)A.a) | "," | valueE((ACD)A.a) | nl; 59 sout | "Symbol b: (20) " | valueE((B)B.b) | "," | valueE((AB)B.b) | nl; 60 sout | "Symbol ab: (30) " | valueE((AB)AB.ab) | nl; 61 sout | "Symbol c: (40) " | valueE((C)C.c) | "," | valueE((CD)C.c) | "," | valueE((ACD)C.c) | "," | valueE((CD)CD.c)| "," | valueE((ACD)CD.c) | nl; 62 sout | "Symbol d: (50) " | valueE((D)D.d) | "," | valueE((CD)D.d) | "," | valueE((ACD)D.d) | "," | valueE((ACD)CD.d) | nl; 63 sout | "Symbol cd: (60) " | valueE((CD)CD.cd) | "," | valueE((ACD)CD.cd) | nl; 64 sout | "Symbol acd: (70) " | valueE((ACD)ACD.acd) | nl; 65 66 sout | "Function Call:" | nl; 67 sout | "Symbol a: (10) " | identity_t(A.a) | "," | identity_t(ACD.a) | nl; 68 sout | "Symbol c: (40) " | identity_t(C.c) | "," | identity_t(ACD.c) | nl; 69 sout | "Symbol d: (50) " | identity_t(D.d) | "," | identity_t(ACD.d) | nl; 70 sout | "Symbol cd: (60) " | identity_t(CD.cd) | "," | identity_t(ACD.cd) | nl; 71 sout | "Symbol acd: (70) " | identity_t(ACD.acd) | nl; 18 72 }
Note: See TracChangeset
for help on using the changeset viewer.