Changeset 85855b0 for src/ResolvExpr/CandidateFinder.cpp
- Timestamp:
- Jun 10, 2024, 2:43:13 AM (6 weeks ago)
- Branches:
- master
- Children:
- 42cdd07d
- Parents:
- d68de59
- File:
-
- 1 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
Note: See TracChangeset
for help on using the changeset viewer.