- File:
-
- 1 edited
-
src/ResolvExpr/CandidateFinder.cpp (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CandidateFinder.cpp
rab780e6 raf746cc 46 46 #include "AST/Type.hpp" 47 47 #include "Common/utility.h" // for move, copy 48 #include "Parser/parserutility.h" // for notZeroExpr 48 49 #include "SymTab/Mangler.h" 49 50 #include "Tuples/Tuples.h" // for handleTupleAssignment … … 284 285 const CodeLocation & location, 285 286 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs & args, 286 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,287 std::vector< ArgPack > & results, std::size_t & genStart, const ResolveContext & context, 287 288 unsigned nTuples = 0 288 289 ) { … … 294 295 // ^^^ need to handle the case where a tuple has a default argument 295 296 if ( ! instantiateArgument( location, 296 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;297 type, nullptr, args, results, genStart, context, nTuples ) ) return false; 297 298 nTuples = 0; 298 299 } … … 509 510 510 511 // attempt to unify types 511 if ( unify( paramType, argType, env, need, have, open ) ) { 512 ast::ptr<ast::Type> common; 513 if ( unify( paramType, argType, env, need, have, open, common ) ) { 512 514 // 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 ); 515 assert( common ); 516 // auto attrType = common.as<ast::EnumAttrType>(); 517 // if ( attrType && ( attrType->attr == ast::EnumAttribute::Value ) ) { 518 // auto callExpr = new ast::UntypedExpr( 519 // expr->location, new ast::NameExpr( expr->location, "valueE"), {expr} ); 520 // CandidateFinder finder( context, env ); 521 // finder.find( callExpr ); 522 // CandidateList winners = findMinCost( finder.candidates ); 523 // if (winners.size() != 1) { 524 // SemanticError( callExpr, "Ambiguous expression in valueE" ); 525 // } 526 // CandidateRef & choice = winners.front(); 527 // choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 528 529 // results.emplace_back( 530 // i, choice->expr, 531 // std::move( env ), std::move( need ), std::move( have ), std::move( open ), 532 // nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 533 // } else { 534 results.emplace_back( 535 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 536 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 537 //} 516 538 } 517 539 } … … 785 807 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>(); 786 808 if ( !instantiateArgument( location, 787 funcType->params[i], obj->init, args, results, genStart, symtab)) return;809 funcType->params[i], obj->init, args, results, genStart, context)) return; 788 810 } 789 811 goto endMatch; … … 795 817 // no default args for indirect calls 796 818 if ( !instantiateArgument( location, 797 param, nullptr, args, results, genStart, symtab) ) return;819 param, nullptr, args, results, genStart, context ) ) return; 798 820 } 799 821 … … 890 912 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) { 891 913 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 } 914 } else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) { 915 if ( enumInst->base->base ) { 916 CandidateFinder finder( context, tenv ); 917 auto location = aggrExpr->location; 918 auto callExpr = new ast::UntypedExpr( 919 location, new ast::NameExpr( location, "valueE" ), {aggrExpr} 920 ); 921 finder.find( callExpr ); 922 CandidateList winners = findMinCost( finder.candidates ); 923 if (winners.size() != 1) { 924 SemanticError( callExpr, "Ambiguous expression in valueE" ); 925 } 926 CandidateRef & choice = winners.front(); 927 // choice->cost.incSafe(); 928 candidates.emplace_back( std::move(choice) ); 929 } 930 950 931 } 951 932 } … … 1414 1395 ast::Expr * newExpr = data.combine( nameExpr->location, cost ); 1415 1396 1397 bool bentConversion = false; 1398 if ( auto inst = newExpr->result.as<ast::EnumInstType>() ) { 1399 if ( inst->base && inst->base->base ) { 1400 bentConversion = true; 1401 } 1402 } 1403 1416 1404 CandidateRef newCand = std::make_shared<Candidate>( 1417 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,1405 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, bentConversion? Cost::safe: Cost::zero, 1418 1406 cost ); 1419 1407 … … 1448 1436 auto cand = new Candidate(variableExpr, tenv); 1449 1437 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 1438 } 1511 1439 … … 1586 1514 void Finder::postvisit( const ast::LogicalExpr * logicalExpr ) { 1587 1515 CandidateFinder finder1( context, tenv ); 1588 ast::ptr<ast::Expr> arg1 = createCondExpr( logicalExpr->arg1 );1516 ast::ptr<ast::Expr> arg1 = notZeroExpr( logicalExpr->arg1 ); 1589 1517 finder1.find( arg1, ResolveMode::withAdjustment() ); 1590 1518 if ( finder1.candidates.empty() ) return; 1591 1519 1592 1520 CandidateFinder finder2( context, tenv ); 1593 ast::ptr<ast::Expr> arg2 = createCondExpr( logicalExpr->arg2 );1521 ast::ptr<ast::Expr> arg2 = notZeroExpr( logicalExpr->arg2 ); 1594 1522 finder2.find( arg2, ResolveMode::withAdjustment() ); 1595 1523 if ( finder2.candidates.empty() ) return; … … 1617 1545 void Finder::postvisit( const ast::ConditionalExpr * conditionalExpr ) { 1618 1546 // candidates for condition 1619 ast::ptr<ast::Expr> arg1 = createCondExpr( conditionalExpr->arg1 );1547 ast::ptr<ast::Expr> arg1 = notZeroExpr( conditionalExpr->arg1 ); 1620 1548 CandidateFinder finder1( context, tenv ); 1621 1549 finder1.find( arg1, ResolveMode::withAdjustment() ); … … 1839 1767 1840 1768 // unification run for side-effects 1841 bool canUnify = unify( toType, cand->expr->result, env, need, have, open ); 1769 ast::ptr<ast::Type> common; 1770 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, common ); 1842 1771 (void) canUnify; 1843 1772 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), … … 1864 1793 // ambiguous case, still output candidates to print in error message 1865 1794 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 ); 1876 } 1877 } 1795 auto commonAsEnumAttr = common.as<ast::EnumAttrType>(); 1796 if ( commonAsEnumAttr && commonAsEnumAttr->attr == ast::EnumAttribute::Value ) { 1797 1798 auto callExpr = new ast::UntypedExpr( 1799 cand->expr->location, new ast::NameExpr( cand->expr->location, "valueE"), {cand->expr} ); 1800 CandidateFinder finder( context, env ); 1801 finder.find( callExpr ); 1802 CandidateList winners = findMinCost( finder.candidates ); 1803 if (winners.size() != 1) { 1804 SemanticError( callExpr, "Ambiguous expression in valueE" ); 1805 } 1806 CandidateRef & choice = winners.front(); 1807 // assert( valueCall->result ); 1808 CandidateRef newCand = std::make_shared<Candidate>( 1809 new ast::InitExpr{ 1810 initExpr->location, 1811 // restructureCast( cand->expr, toType ), 1812 choice->expr, 1813 initAlt.designation }, 1814 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1815 inferParameters( newCand, matches ); 1816 } else { 1817 CandidateRef newCand = std::make_shared<Candidate>( 1818 new ast::InitExpr{ 1819 initExpr->location, 1820 restructureCast( cand->expr, toType ), 1821 initAlt.designation }, 1822 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1823 // currently assertions are always resolved immediately so this should have no effect. 1824 // if this somehow changes in the future (e.g. delayed by indeterminate return type) 1825 // we may need to revisit the logic. 1826 inferParameters( newCand, matches ); 1827 } 1828 } 1829 } 1878 1830 } 1879 1831 } … … 1900 1852 std::make_shared<Candidate>( 1901 1853 newExpr, copy( tenv ), ast::OpenVarSet{}, 1902 ast::AssertionSet{}, Cost:: zero, cost1854 ast::AssertionSet{}, Cost::safe, cost 1903 1855 ); 1904 1856 … … 2200 2152 } 2201 2153 2202 const ast::Expr * createCondExpr( const ast::Expr * expr ) { 2203 assert( expr ); 2204 return new ast::CastExpr( expr->location, 2205 ast::UntypedExpr::createCall( expr->location, 2206 "?!=?", 2207 { 2208 expr, 2209 new ast::ConstantExpr( expr->location, 2210 new ast::ZeroType(), "0", std::make_optional( 0ull ) 2211 ), 2212 } 2213 ), 2214 new ast::BasicType( ast::BasicType::SignedInt ) 2215 ); 2154 // get the valueE(...) ApplicationExpr that returns the enum value 2155 const ast::Expr * getValueEnumCall( 2156 const ast::Expr * expr, 2157 const ResolvExpr::ResolveContext & context, const ast::TypeEnvironment & env ) { 2158 auto callExpr = new ast::UntypedExpr( 2159 expr->location, new ast::NameExpr( expr->location, "valueE"), {expr} ); 2160 CandidateFinder finder( context, env ); 2161 finder.find( callExpr ); 2162 CandidateList winners = findMinCost( finder.candidates ); 2163 if (winners.size() != 1) { 2164 SemanticError( callExpr, "Ambiguous expression in valueE" ); 2165 } 2166 CandidateRef & choice = winners.front(); 2167 return choice->expr; 2168 // return std::move( choice->expr.get() ); 2216 2169 } 2217 2170
Note:
See TracChangeset
for help on using the changeset viewer.