- File:
-
- 1 edited
-
src/ResolvExpr/CandidateFinder.cpp (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CandidateFinder.cpp
rab780e6 r7a780ad 284 284 const CodeLocation & location, 285 285 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs & args, 286 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,286 std::vector< ArgPack > & results, std::size_t & genStart, const ResolveContext & context, 287 287 unsigned nTuples = 0 288 288 ) { … … 294 294 // ^^^ need to handle the case where a tuple has a default argument 295 295 if ( ! instantiateArgument( location, 296 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;296 type, nullptr, args, results, genStart, context, nTuples ) ) return false; 297 297 nTuples = 0; 298 298 } … … 509 509 510 510 // attempt to unify types 511 if ( unify( paramType, argType, env, need, have, open ) ) { 511 ast::ptr<ast::Type> common; 512 if ( unify( paramType, argType, env, need, have, open, common ) ) { 512 513 // add new result 513 results.emplace_back( 514 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 515 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 514 assert( common ); 515 // auto attrType = common.as<ast::EnumAttrType>(); 516 // if ( attrType && ( attrType->attr == ast::EnumAttribute::Value ) ) { 517 // auto callExpr = new ast::UntypedExpr( 518 // expr->location, new ast::NameExpr( expr->location, "valueE"), {expr} ); 519 // CandidateFinder finder( context, env ); 520 // finder.find( callExpr ); 521 // CandidateList winners = findMinCost( finder.candidates ); 522 // if (winners.size() != 1) { 523 // SemanticError( callExpr, "Ambiguous expression in valueE" ); 524 // } 525 // CandidateRef & choice = winners.front(); 526 // choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 527 528 // results.emplace_back( 529 // i, choice->expr, 530 // std::move( env ), std::move( need ), std::move( have ), std::move( open ), 531 // nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 532 // } else { 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 ); 536 //} 516 537 } 517 538 } … … 785 806 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>(); 786 807 if ( !instantiateArgument( location, 787 funcType->params[i], obj->init, args, results, genStart, symtab)) return;808 funcType->params[i], obj->init, args, results, genStart, context)) return; 788 809 } 789 810 goto endMatch; … … 795 816 // no default args for indirect calls 796 817 if ( !instantiateArgument( location, 797 param, nullptr, args, results, genStart, symtab) ) return;818 param, nullptr, args, results, genStart, context ) ) return; 798 819 } 799 820 … … 890 911 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) { 891 912 addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" ); 892 } 893 else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) { 894 if (enumInst->base && enumInst->base->base) { 895 const CodeLocation &location = cand->expr->location; 896 897 CandidateFinder funcFinder(context, tenv); 898 auto nameExpr = new ast::NameExpr(location, "valueE"); 899 ResolveMode mode = {true, false, selfFinder.candidates.empty()}; 900 funcFinder.find( nameExpr, mode ); 901 902 // make variableExpr itself the candidate for the value Call 903 ExplodedArgs argExpansions; 904 argExpansions.emplace_back(); 905 auto &argE = argExpansions.back(); 906 907 argE.emplace_back(*cand, symtab); // Use the typed name expr as param for value 908 909 CandidateList found; 910 SemanticErrorException errors; 911 912 for (CandidateRef &func : funcFinder) { 913 try { 914 const ast::Type *funcResult = 915 func->expr->result->stripReferences(); 916 if (auto pointer = dynamic_cast<const ast::PointerType *>( 917 funcResult)) { 918 if (auto function = 919 pointer->base.as<ast::FunctionType>()) { 920 CandidateRef newFunc{new Candidate{*func}}; 921 newFunc->expr = referenceToRvalueConversion( 922 newFunc->expr, newFunc->cost); 923 makeFunctionCandidates( location, 924 newFunc, function, 925 argExpansions, found ); 926 } 927 } 928 } catch (SemanticErrorException &e) { 929 std::cerr 930 << "Resolving value function should cause an error" 931 << std::endl; 932 errors.append(e); 933 } 934 } 935 936 if (found.empty()) { 937 std::cerr << "Resolve value function should always success" 938 << std::endl; 939 } 940 941 for (CandidateRef &withFunc : found) { 942 withFunc->cost.incSafe(); 943 Cost cvtCost = 944 computeApplicationConversionCost(withFunc, symtab); 945 assert(cvtCost != Cost::infinity); 946 947 candidates.emplace_back(std::move(withFunc)); 948 } 949 } 913 } else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) { 914 if ( enumInst->base->base ) { 915 CandidateFinder finder( context, tenv ); 916 auto location = aggrExpr->location; 917 auto callExpr = new ast::UntypedExpr( 918 location, new ast::NameExpr( location, "valueE" ), {aggrExpr} 919 ); 920 finder.find( callExpr ); 921 CandidateList winners = findMinCost( finder.candidates ); 922 if (winners.size() != 1) { 923 SemanticError( callExpr, "Ambiguous expression in valueE" ); 924 } 925 CandidateRef & choice = winners.front(); 926 // choice->cost.incSafe(); 927 candidates.emplace_back( std::move(choice) ); 928 } 929 950 930 } 951 931 } … … 1414 1394 ast::Expr * newExpr = data.combine( nameExpr->location, cost ); 1415 1395 1396 bool bentConversion = false; 1397 if ( auto inst = newExpr->result.as<ast::EnumInstType>() ) { 1398 if ( inst->base && inst->base->base ) { 1399 bentConversion = true; 1400 } 1401 } 1402 1416 1403 CandidateRef newCand = std::make_shared<Candidate>( 1417 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,1404 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, bentConversion? Cost::safe: Cost::zero, 1418 1405 cost ); 1419 1406 … … 1448 1435 auto cand = new Candidate(variableExpr, tenv); 1449 1436 candidates.emplace_back(cand); 1450 1451 if (auto enumInst = dynamic_cast<const ast::EnumInstType *>(1452 variableExpr->var->get_type())) {1453 if (enumInst->base && enumInst->base->base) {1454 const CodeLocation &location = cand->expr->location;1455 1456 CandidateFinder funcFinder(context, tenv);1457 auto nameExpr = new ast::NameExpr(location, "valueE");1458 ResolveMode mode = {true, false, selfFinder.candidates.empty()};1459 funcFinder.find( nameExpr, mode );1460 1461 // make variableExpr itself the candidate for the value Call1462 ExplodedArgs argExpansions;1463 argExpansions.emplace_back();1464 auto &argE = argExpansions.back();1465 1466 argE.emplace_back(*cand, symtab);1467 1468 CandidateList found;1469 SemanticErrorException errors;1470 1471 for (CandidateRef &func : funcFinder) {1472 try {1473 const ast::Type *funcResult =1474 func->expr->result->stripReferences();1475 if (auto pointer = dynamic_cast<const ast::PointerType *>(1476 funcResult)) {1477 if (auto function =1478 pointer->base.as<ast::FunctionType>()) {1479 CandidateRef newFunc{new Candidate{*func}};1480 newFunc->expr = referenceToRvalueConversion(1481 newFunc->expr, newFunc->cost);1482 makeFunctionCandidates(variableExpr->location,1483 newFunc, function,1484 argExpansions, found);1485 }1486 }1487 } catch (SemanticErrorException &e) {1488 std::cerr1489 << "Resolving value function should cause an error"1490 << std::endl;1491 errors.append(e);1492 }1493 }1494 1495 if (found.empty()) {1496 std::cerr << "Resolve value function should always success"1497 << std::endl;1498 }1499 1500 for (CandidateRef &withFunc : found) {1501 withFunc->cost.incSafe();1502 Cost cvtCost =1503 computeApplicationConversionCost(withFunc, symtab);1504 assert(cvtCost != Cost::infinity);1505 1506 candidates.emplace_back(std::move(withFunc));1507 }1508 }1509 }1510 1437 } 1511 1438 … … 1839 1766 1840 1767 // unification run for side-effects 1841 bool canUnify = unify( toType, cand->expr->result, env, need, have, open ); 1768 ast::ptr<ast::Type> common; 1769 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, common ); 1842 1770 (void) canUnify; 1843 1771 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), … … 1864 1792 // ambiguous case, still output candidates to print in error message 1865 1793 if ( cand->cost == minExprCost && thisCost == minCastCost ) { 1866 CandidateRef newCand = std::make_shared<Candidate>( 1867 new ast::InitExpr{ 1868 initExpr->location, 1869 restructureCast( cand->expr, toType ), 1870 initAlt.designation }, 1871 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1872 // currently assertions are always resolved immediately so this should have no effect. 1873 // if this somehow changes in the future (e.g. delayed by indeterminate return type) 1874 // we may need to revisit the logic. 1875 inferParameters( newCand, matches ); 1794 auto commonAsEnumAttr = common.as<ast::EnumAttrType>(); 1795 if ( commonAsEnumAttr && commonAsEnumAttr->attr == ast::EnumAttribute::Value ) { 1796 auto callExpr = new ast::UntypedExpr( 1797 cand->expr->location, new ast::NameExpr( cand->expr->location, "valueE"), {cand->expr} ); 1798 CandidateFinder finder( context, env ); 1799 finder.find( callExpr ); 1800 CandidateList winners = findMinCost( finder.candidates ); 1801 if (winners.size() != 1) { 1802 SemanticError( callExpr, "Ambiguous expression in valueE" ); 1803 } 1804 CandidateRef & choice = winners.front(); 1805 // assert( valueCall->result ); 1806 CandidateRef newCand = std::make_shared<Candidate>( 1807 new ast::InitExpr{ 1808 initExpr->location, 1809 // restructureCast( cand->expr, toType ), 1810 choice->expr, 1811 initAlt.designation }, 1812 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1813 inferParameters( newCand, matches ); 1814 } else { 1815 CandidateRef newCand = std::make_shared<Candidate>( 1816 new ast::InitExpr{ 1817 initExpr->location, 1818 restructureCast( cand->expr, toType ), 1819 initAlt.designation }, 1820 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1821 // currently assertions are always resolved immediately so this should have no effect. 1822 // if this somehow changes in the future (e.g. delayed by indeterminate return type) 1823 // we may need to revisit the logic. 1824 inferParameters( newCand, matches ); 1825 } 1876 1826 } 1877 1827 } … … 1900 1850 std::make_shared<Candidate>( 1901 1851 newExpr, copy( tenv ), ast::OpenVarSet{}, 1902 ast::AssertionSet{}, Cost:: zero, cost1852 ast::AssertionSet{}, Cost::safe, cost 1903 1853 ); 1904 1854 … … 2200 2150 } 2201 2151 2152 const ast::Expr * getValueEnumCall( const ast::Expr * expr, 2153 const ResolveContext & context, const ast::TypeEnvironment & env ) { 2154 auto callExpr = new ast::UntypedExpr( 2155 expr->location, new ast::NameExpr( expr->location, "valueE"), {expr} ); 2156 CandidateFinder finder( context, env ); 2157 finder.find( callExpr ); 2158 CandidateList winners = findMinCost( finder.candidates ); 2159 if (winners.size() != 1) { 2160 SemanticError( callExpr, "Ambiguous expression in valueE" ); 2161 } 2162 CandidateRef & choice = winners.front(); 2163 return choice->expr; 2164 } 2165 2202 2166 const ast::Expr * createCondExpr( const ast::Expr * expr ) { 2203 2167 assert( expr ); … … 2212 2176 } 2213 2177 ), 2214 new ast::BasicType( ast::Basic Type::SignedInt )2178 new ast::BasicType( ast::BasicKind::SignedInt ) 2215 2179 ); 2216 2180 }
Note:
See TracChangeset
for help on using the changeset viewer.