Changeset 85855b0 for src/ResolvExpr
- Timestamp:
- Jun 10, 2024, 2:43:13 AM (8 months ago)
- Branches:
- master
- Children:
- 42cdd07d
- Parents:
- d68de59
- Location:
- src/ResolvExpr
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CandidateFinder.cpp
rd68de59 r85855b0 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
rd68de59 r85855b0 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
rd68de59 r85855b0 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
rd68de59 r85855b0 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
rd68de59 r85855b0 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
rd68de59 r85855b0 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(
Note: See TracChangeset
for help on using the changeset viewer.