Changes in / [42cdd07d:0188539c]
- Files:
-
- 24 edited
-
libcfa/prelude/builtins.c (modified) (1 diff)
-
libcfa/src/enum.cfa (modified) (1 diff)
-
libcfa/src/enum.hfa (modified) (1 diff)
-
src/AST/Decl.cpp (modified) (1 diff)
-
src/AST/Decl.hpp (modified) (3 diffs)
-
src/AST/Expr.hpp (modified) (1 diff)
-
src/AST/Pass.impl.hpp (modified) (1 diff)
-
src/AST/SymbolTable.cpp (modified) (1 diff)
-
src/AST/SymbolTable.hpp (modified) (1 diff)
-
src/AST/Util.cpp (modified) (1 diff)
-
src/GenPoly/Lvalue.cpp (modified) (2 diffs)
-
src/Parser/TypeData.cpp (modified) (2 diffs)
-
src/Parser/parser.yy (modified) (1 diff)
-
src/ResolvExpr/CandidateFinder.cpp (modified) (13 diffs)
-
src/ResolvExpr/CandidateFinder.hpp (modified) (1 diff)
-
src/ResolvExpr/CastCost.cpp (modified) (3 diffs)
-
src/ResolvExpr/CommonType.cpp (modified) (1 diff)
-
src/ResolvExpr/ConversionCost.cpp (modified) (3 diffs)
-
src/ResolvExpr/Resolver.cpp (modified) (1 diff)
-
src/Validate/Autogen.cpp (modified) (1 diff)
-
src/Validate/EnumAndPointerDecay.cpp (modified) (1 diff)
-
src/Validate/ImplementEnumFunc.cpp (modified) (13 diffs)
-
tests/enum_tests/.expect/enumInlineValue.txt (modified) (1 diff)
-
tests/enum_tests/enumInlineValue.cfa (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/prelude/builtins.c
r42cdd07d r0188539c 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 186 180 // Local Variables: // 187 181 // mode: c // -
libcfa/src/enum.cfa
r42cdd07d r0188539c 1 1 #include "enum.hfa" 2 #include "fstream.hfa"3 2 4 3 #pragma GCC visibility push(default) 5 4 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); 5 forall(T, E| TypedEnum(T, E)) { 6 // constructors 7 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); } 9 16 } 10 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);14 } -
libcfa/src/enum.hfa
r42cdd07d r0188539c 1 1 #pragma once 2 2 3 #include "iostream.hfa" 3 forall(T) { // T is the based type of enum(T) 4 forall(E) trait Bounded { 5 E lowerBound(); 6 E upperBound(); 7 }; 4 8 5 forall(E) trait Bounded { 6 E lowerBound(); 7 E upperBound(); 8 }; 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 }; 9 15 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 }; 16 // Opague Enum + TypedEnum 17 forall(E | Serial(T, E)) trait CfaEnum { 18 char * labelE(E e); 19 unsigned int posE(E e); 20 }; 16 21 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 }; 22 forall(E| CfaEnum(T, E)) trait TypedEnum { 23 T valueE(E e); 24 }; 24 25 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 // }; 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 } -
src/AST/Decl.cpp
r42cdd07d r0188539c 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 } 177 178 } 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;186 }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 }204 179 205 180 } -
src/AST/Decl.hpp
r42cdd07d r0188539c 75 75 bool isDeleted = false; 76 76 bool isTypeFixed = false; 77 bool isHidden = false;78 77 79 78 DeclWithType( const CodeLocation& loc, const std::string& name, Storage::Classes storage, … … 314 313 ptr<Type> base; 315 314 enum class EnumHiding { Visible, Hide } hide; 316 std::vector< ast::ptr<ast::EnumInstType>> inlinedDecl; // child enums317 318 315 EnumDecl( const CodeLocation& loc, const std::string& name, bool isTyped = false, 319 316 std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall, … … 331 328 332 329 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;338 330 private: 339 331 EnumDecl * clone() const override { return new EnumDecl{ *this }; } -
src/AST/Expr.hpp
r42cdd07d r0188539c 256 256 public: 257 257 ptr<Decl> type_decl; 258 const std::string type_name; 259 const std::string name; 258 std::string name; 260 259 261 260 QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & 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 ) {} 261 : Expr( loc ), type_decl( d ), name( n ) {} 266 262 267 263 const Expr * accept( Visitor & v ) const override { return v.visit( this ); } -
src/AST/Pass.impl.hpp
r42cdd07d r0188539c 560 560 561 561 if ( __visit_children() ) { 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 ); 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 } 567 574 } 568 575 -
src/AST/SymbolTable.cpp
r42cdd07d r0188539c 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 173 161 std::vector<SymbolTable::IdData> SymbolTable::specialLookupId( SymbolTable::SpecialFunctionKind kind, const std::string & otypeKey ) const { 174 162 static Stats::Counters::CounterGroup * special_stats = Stats::Counters::build<Stats::Counters::CounterGroup>("Special Lookups"); -
src/AST/SymbolTable.hpp
r42cdd07d r0188539c 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 enumeration124 std::vector<IdData> lookupIdIgnoreHidden( const std::string &id ) const;125 123 /// Gets special functions associated with a type; if no key is given, returns everything 126 124 std::vector<IdData> specialLookupId( SpecialFunctionKind kind, const std::string & otypeKey = "" ) const; -
src/AST/Util.cpp
r42cdd07d r0188539c 352 352 void previsit( EnumDecl const * decl ) { 353 353 enumDecls.insert( decl ); 354 for ( auto & member : decl->members ) { 355 typedDecls.insert( member.strict_as<ast::DeclWithType>() ); 354 if ( ast::EnumDecl::EnumHiding::Visible == decl->hide ) { 355 for ( auto & member : decl->members ) { 356 typedDecls.insert( member.strict_as<ast::DeclWithType>() ); 357 } 356 358 } 357 359 beginScope(); -
src/GenPoly/Lvalue.cpp
r42cdd07d r0188539c 389 389 assert( 0 == diff ); 390 390 // Remove useless generated casts. 391 if ( expr->isGenerated == ast::GeneratedFlag::GeneratedCast&&391 if ( expr->isGenerated && 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 }407 400 return ast::mutate_field( expr->arg.get(), 408 401 &ast::Expr::env, expr->env.get() ); -
src/Parser/TypeData.cpp
r42cdd07d r0188539c 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) 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() ) { 1467 if ( cur->enumInLine ) { 1468 // Do Nothing 1469 } else if ( ret->isTyped && !ret->base && cur->has_enumeratorValue() ) { 1472 1470 SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." ); 1473 1471 } 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 } 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 } 1480 1484 // else cur is a List Initializer and has been set as init in buildList() 1481 1485 // if -
src/Parser/parser.yy
r42cdd07d r0188539c 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 2830 { $$ = $1->set_last( DeclarationNode::newEnum InLine( $4->symbolic.name )); }2829 | enumerator_list ',' INLINE type_name enumerator_value_opt 2830 { $$ = $1->set_last( DeclarationNode::newEnumValueGeneric( new string("inline"), nullptr ) ); } 2831 2831 ; 2832 2832 -
src/ResolvExpr/CandidateFinder.cpp
r42cdd07d r0188539c 513 513 // add new result 514 514 assert( common ); 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 ); 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 //} 536 519 } 537 520 } … … 649 632 const ast::BaseInstType * aggrInst, const ast::Expr * expr, 650 633 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 & addedCost655 634 ); 656 635 … … 697 676 void postvisit( const ast::QualifiedNameExpr * qualifiedExpr ); 698 677 699 const ast::Expr * makeEnumOffsetCast( const ast::EnumInstType * src,700 const ast::EnumInstType * dst701 , const ast::Expr * expr, Cost minCost );702 703 678 void postvisit( const ast::InitExpr * ) { 704 679 assertf( false, "CandidateFinder should never see a resolved InitExpr." ); … … 901 876 } 902 877 903 void Finder::addEnumValueAsCandidate( const ast::EnumInstType * enumInst, const ast::Expr * expr,904 const Cost & addedCost905 ) {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 924 878 /// Adds implicit struct-conversions to the alternative list 925 879 void Finder::addAnonConversions( const CandidateRef & cand ) { … … 940 894 addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" ); 941 895 } else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) { 942 addEnumValueAsCandidate(enumInst, aggrExpr, Cost::unsafe); 943 } 944 } 945 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 } 946 914 947 915 /// Adds aggregate member interpretations … … 1212 1180 } 1213 1181 1214 // src is a subset of dst1215 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 1257 1182 void Finder::postvisit( const ast::CastExpr * castExpr ) { 1258 1183 ast::ptr< ast::Type > toType = castExpr->result; … … 1304 1229 ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ) 1305 1230 : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ); 1306 1307 // Redefine enum cast1308 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 }1314 1231 1315 1232 PRINT( … … 1329 1246 minCastCost = thisCost; 1330 1247 matches.clear(); 1331 } 1332 // ambigious case, still output candidates to print in error message 1248 1249 1250 } 1251 // ambiguous case, still output candidates to print in error message 1333 1252 if ( cand->cost == minExprCost && thisCost == minCastCost ) { 1334 1253 CandidateRef newCand = std::make_shared<Candidate>( … … 1345 1264 } 1346 1265 candidates = std::move(matches); 1266 1347 1267 //CandidateList minArgCost = findMinCost( matches ); 1348 1268 //promoteCvtCost( minArgCost ); … … 1454 1374 } 1455 1375 } else { 1456 declList = symtab.lookupId IgnoreHidden( nameExpr->name );1376 declList = symtab.lookupId( nameExpr->name ); 1457 1377 } 1458 1378 PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; ) … … 1466 1386 ast::Expr * newExpr = data.combine( nameExpr->location, cost ); 1467 1387 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 ); 1468 1398 CandidateRef newCand = std::make_shared<Candidate>( 1469 1399 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, … … 1883 1813 if ( const ast::EnumInstType * enumInstType = 1884 1814 dynamic_cast<const ast::EnumInstType *>( t ) ) { 1885 if ( (enumInstType->base->name == expr->type_name) 1886 || (expr->type_decl && enumInstType->base->name == expr->type_decl->name) ) { 1815 if ( enumInstType->base->name == expr->type_decl->name ) { 1887 1816 Cost cost = Cost::zero; 1888 1817 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, cost 1822 // ); 1889 1823 CandidateRef newCand = 1890 1824 std::make_shared<Candidate>( … … 2162 2096 2163 2097 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;2203 2098 } 2204 2099 -
src/ResolvExpr/CandidateFinder.hpp
r42cdd07d r0188539c 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 );63 60 }; 64 61 -
src/ResolvExpr/CastCost.cpp
r42cdd07d r0188539c 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 & env41 );42 43 38 namespace { 44 39 struct CastCost : public ConversionCost { … … 50 45 const ast::TypeEnvironment & env, CostCalculation costFunc ) 51 46 : ConversionCost( dst, srcIsLvalue, symtab, env, costFunc ) {} 52 53 void postvisit( const ast::EnumInstType * enumInst ) {54 cost = conversionCost( enumInst, dst, srcIsLvalue, symtab, env );55 }56 47 57 48 void postvisit( const ast::BasicType * basicType ) { … … 113 104 cost = Cost::unsafe; 114 105 } 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; 115 112 } 116 113 } -
src/ResolvExpr/CommonType.cpp
r42cdd07d r0188539c 636 636 void postvisit( const ast::UnionInstType * ) {} 637 637 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 ) { 638 void postvisit( const ast::EnumInstType * enumInst ) { 639 if ( enumInst->base && !enumInst->base->isTyped ) { 645 640 auto basicType = new ast::BasicType( ast::BasicKind::UnsignedInt ); 646 641 result = commonType( basicType, type2, tenv, need, have, open, widen); -
src/ResolvExpr/ConversionCost.cpp
r42cdd07d r0188539c 191 191 } 192 192 193 Cost enumCastCost (194 const ast::EnumInstType * src, const ast::EnumInstType * dst,195 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env196 );197 198 193 static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue, 199 194 int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, … … 364 359 365 360 void ConversionCost::postvisit( const ast::EnumInstType * inst ) { 366 if ( auto dstInst = dynamic_cast<const ast::EnumInstType *>( dst ) ) { 367 cost = enumCastCost(inst, dstInst, symtab, env); 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 } 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 & env487 ) {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 500 483 // size_t ConversionCost::traceId = Stats::Heap::new_stacktrace_id("ConversionCost"); 501 484 -
src/ResolvExpr/Resolver.cpp
r42cdd07d r0188539c 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 }211 203 // generated cast is the same type as its argument, remove it after keeping env 212 204 return ast::mutate_field( -
src/Validate/Autogen.cpp
r42cdd07d r0188539c 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
r42cdd07d r0188539c 47 47 new ast::EnumInstType( decl, ast::CV::Const ) ) ); 48 48 } else if ( auto value = member.as<ast::InlineMemberDecl>() ) { 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 )); 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 } 71 66 } 72 67 } -
src/Validate/ImplementEnumFunc.cpp
r42cdd07d r0188539c 10 10 const ast::EnumDecl* decl; 11 11 unsigned int functionNesting; 12 const ast::StructDecl* quasi_void_decl;13 12 ast::Linkage::Spec proto_linkage; 14 13 … … 25 24 : decl(decl), 26 25 functionNesting{functionNesting}, 27 quasi_void_decl(new ast::StructDecl(decl->location,28 "quasi_void", ast::AggregateDecl::Struct,29 {}, ast::Linkage::AutoGen)),30 26 proto_linkage{ast::Linkage::Cforall} {} 31 27 … … 56 52 void genSuccPredBody(ast::FunctionDecl *, const char *) const; 57 53 58 void genTypeNameFunc();59 60 54 // Implement TypedEnum trait 61 55 void genTypedEnumFuncs(); … … 64 58 ast::FunctionDecl* genLabelProto() const; 65 59 ast::FunctionDecl* genValueProto() const; 66 ast::FunctionDecl* genQuasiValueProto() const;67 ast::FunctionDecl* genTypeNameProto() const;68 69 60 void genValueOrLabelBody( 70 61 ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const; 71 62 void genPosnBody(ast::FunctionDecl* func) const; 72 void genQuasiValueBody(ast::FunctionDecl* func) const; 73 void genTypeNameBody(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 } 74 73 75 74 // ---------------------------------------------------- … … 118 117 return inits; 119 118 } 120 121 119 const ast::Init* EnumAttrFuncGenerator::getAutoInit( 122 120 const ast::Init* prev) const { … … 191 189 192 190 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 else200 return genQuasiValueProto();201 }202 203 ast::FunctionDecl* EnumAttrFuncGenerator::genQuasiValueProto() const {204 191 return genProto( 205 192 "valueE", 206 193 {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))}, 207 194 {new ast::ObjectDecl(getLocation(), "_ret", 208 new ast::StructInstType(quasi_void_decl))});195 ast::deepCopy(decl->base))}); 209 196 } 210 197 … … 223 210 {new ast::ObjectDecl(getLocation(), "_ret", new ast::BasicType(ast::BasicKind::UnsignedInt))} 224 211 ); 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}))});234 212 } 235 213 … … 290 268 ); 291 269 } 270 292 271 293 272 void EnumAttrFuncGenerator::genSerialTraitFuncs() { … … 323 302 const CodeLocation & loc = func->location; 324 303 auto mem = func->name=="lowerBound"? decl->members.front() : decl->members.back(); 325 // auto expr = new ast::NameExpr( loc, mem->name ); 326 auto expr = new ast::QualifiedNameExpr( loc, decl->name, mem->name ); 304 auto expr = new ast::NameExpr( loc, mem->name ); 327 305 func->stmts = new ast::CompoundStmt( loc, {new ast::ReturnStmt(loc, expr)}); 328 306 } … … 371 349 } 372 350 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 386 351 void EnumAttrFuncGenerator::genPosnBody(ast::FunctionDecl* func) const { 387 352 auto castExpr = new ast::CastExpr( … … 394 359 } 395 360 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 403 361 void EnumAttrFuncGenerator::genTypedEnumFunction(const ast::EnumAttribute attr) { 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(); 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(); 424 367 ast::ObjectDecl* arrayProto = 425 368 genAttrArrayProto(attr, getLocation(), inits); 426 369 forwards.push_back(arrayProto); 427 ast::FunctionDecl* funcProto = genLabelProto(); 370 371 ast::FunctionDecl* funcProto = ( attr == ast::EnumAttribute::Value ) 372 ? genValueProto() 373 : genLabelProto(); 428 374 produceForwardDecl(funcProto); 429 375 genValueOrLabelBody(funcProto, arrayProto); … … 438 384 439 385 void EnumAttrFuncGenerator::genTypedEnumFuncs() { 440 genTypedEnumFunction(ast::EnumAttribute::Value);386 if (decl->base) genTypedEnumFunction(ast::EnumAttribute::Value); 441 387 genTypedEnumFunction(ast::EnumAttribute::Label); 442 388 genTypedEnumFunction(ast::EnumAttribute::Posn); 443 }444 445 void EnumAttrFuncGenerator::genTypeNameFunc() {446 ast::FunctionDecl* funcProto = genTypeNameProto();447 produceForwardDecl(funcProto);448 genTypeNameBody(funcProto);449 produceDecl(funcProto);450 389 } 451 390 … … 453 392 std::list<ast::ptr<ast::Decl>>& decls) { 454 393 // Generate the functions (they go into forwards and definitions). 455 genTypeNameFunc();456 394 genTypedEnumFuncs(); 457 395 genSerialTraitFuncs(); -
tests/enum_tests/.expect/enumInlineValue.txt
r42cdd07d r0188539c 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 1 enumB.A is 5 2 enumB.B is 6 3 enumB.D is 11 4 enumB.E is 12 -
tests/enum_tests/enumInlineValue.cfa
r42cdd07d r0188539c 1 1 #include <fstream.hfa> 2 #include <enum.hfa> 3 4 enum(int) A !{ 5 a = 10 2 enum enumA { 3 A=5, B, C=10, D 6 4 }; 7 5 8 enum(int) B { 9 b = 20 6 enum enumB { 7 inline enumA, 8 E 10 9 }; 11 10 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); 11 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; 43 18 } 44 45 int main() {46 // Note: We need to use qualified name syntax even if no ! hidding47 // Because Inline introduce ambiguity on symbols48 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;72 }
Note:
See TracChangeset
for help on using the changeset viewer.