- File:
-
- 1 edited
-
src/ResolvExpr/CandidateFinder.cpp (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/CandidateFinder.cpp
raf746cc rab780e6 46 46 #include "AST/Type.hpp" 47 47 #include "Common/utility.h" // for move, copy 48 #include "Parser/parserutility.h" // for notZeroExpr49 48 #include "SymTab/Mangler.h" 50 49 #include "Tuples/Tuples.h" // for handleTupleAssignment … … 285 284 const CodeLocation & location, 286 285 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs & args, 287 std::vector< ArgPack > & results, std::size_t & genStart, const ResolveContext & context,286 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 288 287 unsigned nTuples = 0 289 288 ) { … … 295 294 // ^^^ need to handle the case where a tuple has a default argument 296 295 if ( ! instantiateArgument( location, 297 type, nullptr, args, results, genStart, context, nTuples ) ) return false;296 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false; 298 297 nTuples = 0; 299 298 } … … 510 509 511 510 // attempt to unify types 512 ast::ptr<ast::Type> common; 513 if ( unify( paramType, argType, env, need, have, open, common ) ) { 511 if ( unify( paramType, argType, env, need, have, open ) ) { 514 512 // add new result 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 //} 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 ); 538 516 } 539 517 } … … 807 785 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>(); 808 786 if ( !instantiateArgument( location, 809 funcType->params[i], obj->init, args, results, genStart, context)) return;787 funcType->params[i], obj->init, args, results, genStart, symtab)) return; 810 788 } 811 789 goto endMatch; … … 817 795 // no default args for indirect calls 818 796 if ( !instantiateArgument( location, 819 param, nullptr, args, results, genStart, context) ) return;797 param, nullptr, args, results, genStart, symtab ) ) return; 820 798 } 821 799 … … 912 890 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) { 913 891 addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" ); 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 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 } 931 950 } 932 951 } … … 1395 1414 ast::Expr * newExpr = data.combine( nameExpr->location, cost ); 1396 1415 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 1404 1416 CandidateRef newCand = std::make_shared<Candidate>( 1405 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, bentConversion? Cost::safe:Cost::zero,1417 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1406 1418 cost ); 1407 1419 … … 1436 1448 auto cand = new Candidate(variableExpr, tenv); 1437 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 } 1438 1510 } 1439 1511 … … 1514 1586 void Finder::postvisit( const ast::LogicalExpr * logicalExpr ) { 1515 1587 CandidateFinder finder1( context, tenv ); 1516 ast::ptr<ast::Expr> arg1 = notZeroExpr( logicalExpr->arg1 );1588 ast::ptr<ast::Expr> arg1 = createCondExpr( logicalExpr->arg1 ); 1517 1589 finder1.find( arg1, ResolveMode::withAdjustment() ); 1518 1590 if ( finder1.candidates.empty() ) return; 1519 1591 1520 1592 CandidateFinder finder2( context, tenv ); 1521 ast::ptr<ast::Expr> arg2 = notZeroExpr( logicalExpr->arg2 );1593 ast::ptr<ast::Expr> arg2 = createCondExpr( logicalExpr->arg2 ); 1522 1594 finder2.find( arg2, ResolveMode::withAdjustment() ); 1523 1595 if ( finder2.candidates.empty() ) return; … … 1545 1617 void Finder::postvisit( const ast::ConditionalExpr * conditionalExpr ) { 1546 1618 // candidates for condition 1547 ast::ptr<ast::Expr> arg1 = notZeroExpr( conditionalExpr->arg1 );1619 ast::ptr<ast::Expr> arg1 = createCondExpr( conditionalExpr->arg1 ); 1548 1620 CandidateFinder finder1( context, tenv ); 1549 1621 finder1.find( arg1, ResolveMode::withAdjustment() ); … … 1767 1839 1768 1840 // unification run for side-effects 1769 ast::ptr<ast::Type> common; 1770 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, common ); 1841 bool canUnify = unify( toType, cand->expr->result, env, need, have, open ); 1771 1842 (void) canUnify; 1772 1843 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), … … 1793 1864 // ambiguous case, still output candidates to print in error message 1794 1865 if ( cand->cost == minExprCost && thisCost == minCastCost ) { 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 } 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 } 1830 1878 } 1831 1879 } … … 1852 1900 std::make_shared<Candidate>( 1853 1901 newExpr, copy( tenv ), ast::OpenVarSet{}, 1854 ast::AssertionSet{}, Cost:: safe, cost1902 ast::AssertionSet{}, Cost::zero, cost 1855 1903 ); 1856 1904 … … 2152 2200 } 2153 2201 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() ); 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 ); 2169 2216 } 2170 2217
Note:
See TracChangeset
for help on using the changeset viewer.