Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CandidateFinder.cpp

    raf746cc rab780e6  
    4646#include "AST/Type.hpp"
    4747#include "Common/utility.h"       // for move, copy
    48 #include "Parser/parserutility.h" // for notZeroExpr
    4948#include "SymTab/Mangler.h"
    5049#include "Tuples/Tuples.h"        // for handleTupleAssignment
     
    285284                const CodeLocation & location,
    286285                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,
    288287                unsigned nTuples = 0
    289288        ) {
     
    295294                                // ^^^ need to handle the case where a tuple has a default argument
    296295                                if ( ! instantiateArgument( location,
    297                                         type, nullptr, args, results, genStart, context, nTuples ) ) return false;
     296                                        type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;
    298297                                nTuples = 0;
    299298                        }
     
    510509
    511510                                // 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 ) ) {
    514512                                        // 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 );
    538516                                }
    539517                        }
     
    807785                                        auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>();
    808786                                        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;
    810788                                }
    811789                                goto endMatch;
     
    817795                        // no default args for indirect calls
    818796                        if ( !instantiateArgument( location,
    819                                 param, nullptr, args, results, genStart, context ) ) return;
     797                                param, nullptr, args, results, genStart, symtab ) ) return;
    820798                }
    821799
     
    912890                } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) {
    913891                        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        }
    931950                }
    932951        }
     
    13951414                        ast::Expr * newExpr = data.combine( nameExpr->location, cost );
    13961415
    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                        
    14041416                        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,
    14061418                                cost );
    14071419
     
    14361448        auto cand = new Candidate(variableExpr, tenv);
    14371449        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        }
    14381510    }
    14391511
     
    15141586        void Finder::postvisit( const ast::LogicalExpr * logicalExpr ) {
    15151587                CandidateFinder finder1( context, tenv );
    1516                 ast::ptr<ast::Expr> arg1 = notZeroExpr( logicalExpr->arg1 );
     1588                ast::ptr<ast::Expr> arg1 = createCondExpr( logicalExpr->arg1 );
    15171589                finder1.find( arg1, ResolveMode::withAdjustment() );
    15181590                if ( finder1.candidates.empty() ) return;
    15191591
    15201592                CandidateFinder finder2( context, tenv );
    1521                 ast::ptr<ast::Expr> arg2 = notZeroExpr( logicalExpr->arg2 );
     1593                ast::ptr<ast::Expr> arg2 = createCondExpr( logicalExpr->arg2 );
    15221594                finder2.find( arg2, ResolveMode::withAdjustment() );
    15231595                if ( finder2.candidates.empty() ) return;
     
    15451617        void Finder::postvisit( const ast::ConditionalExpr * conditionalExpr ) {
    15461618                // candidates for condition
    1547                 ast::ptr<ast::Expr> arg1 = notZeroExpr( conditionalExpr->arg1 );
     1619                ast::ptr<ast::Expr> arg1 = createCondExpr( conditionalExpr->arg1 );
    15481620                CandidateFinder finder1( context, tenv );
    15491621                finder1.find( arg1, ResolveMode::withAdjustment() );
     
    17671839
    17681840                                // 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 );
    17711842                                (void) canUnify;
    17721843                                Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     
    17931864                                        // ambiguous case, still output candidates to print in error message
    17941865                                        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                                }
    18301878                        }
    18311879                }
     
    18521900                                                std::make_shared<Candidate>(
    18531901                                                        newExpr, copy( tenv ), ast::OpenVarSet{},
    1854                                                         ast::AssertionSet{}, Cost::safe, cost
     1902                                                        ast::AssertionSet{}, Cost::zero, cost
    18551903                                                );
    18561904
     
    21522200}
    21532201
    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() );
     2202const 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        );
    21692216}
    21702217
Note: See TracChangeset for help on using the changeset viewer.