- File:
-
- 1 edited
-
src/ResolvExpr/CandidateFinder.cpp (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CandidateFinder.cpp
r7a780ad rab780e6 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 ResolveContext & context,286 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 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, context, nTuples ) ) return false;296 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false; 297 297 nTuples = 0; 298 298 } … … 509 509 510 510 // attempt to unify types 511 ast::ptr<ast::Type> common; 512 if ( unify( paramType, argType, env, need, have, open, common ) ) { 511 if ( unify( paramType, argType, env, need, have, open ) ) { 513 512 // add new result 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 //} 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 ); 537 516 } 538 517 } … … 806 785 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>(); 807 786 if ( !instantiateArgument( location, 808 funcType->params[i], obj->init, args, results, genStart, context)) return;787 funcType->params[i], obj->init, args, results, genStart, symtab)) return; 809 788 } 810 789 goto endMatch; … … 816 795 // no default args for indirect calls 817 796 if ( !instantiateArgument( location, 818 param, nullptr, args, results, genStart, context) ) return;797 param, nullptr, args, results, genStart, symtab ) ) return; 819 798 } 820 799 … … 911 890 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) { 912 891 addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" ); 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 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 } 930 950 } 931 951 } … … 1394 1414 ast::Expr * newExpr = data.combine( nameExpr->location, cost ); 1395 1415 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 1403 1416 CandidateRef newCand = std::make_shared<Candidate>( 1404 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, bentConversion? Cost::safe:Cost::zero,1417 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1405 1418 cost ); 1406 1419 … … 1435 1448 auto cand = new Candidate(variableExpr, tenv); 1436 1449 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 Call 1462 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::cerr 1489 << "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 } 1437 1510 } 1438 1511 … … 1766 1839 1767 1840 // unification run for side-effects 1768 ast::ptr<ast::Type> common; 1769 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, common ); 1841 bool canUnify = unify( toType, cand->expr->result, env, need, have, open ); 1770 1842 (void) canUnify; 1771 1843 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), … … 1792 1864 // ambiguous case, still output candidates to print in error message 1793 1865 if ( cand->cost == minExprCost && thisCost == minCastCost ) { 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 } 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 ); 1826 1876 } 1827 1877 } … … 1850 1900 std::make_shared<Candidate>( 1851 1901 newExpr, copy( tenv ), ast::OpenVarSet{}, 1852 ast::AssertionSet{}, Cost:: safe, cost1902 ast::AssertionSet{}, Cost::zero, cost 1853 1903 ); 1854 1904 … … 2150 2200 } 2151 2201 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 2166 2202 const ast::Expr * createCondExpr( const ast::Expr * expr ) { 2167 2203 assert( expr ); … … 2176 2212 } 2177 2213 ), 2178 new ast::BasicType( ast::Basic Kind::SignedInt )2214 new ast::BasicType( ast::BasicType::SignedInt ) 2179 2215 ); 2180 2216 }
Note:
See TracChangeset
for help on using the changeset viewer.