Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CandidateFinder.cpp

    rab780e6 raf746cc  
    4646#include "AST/Type.hpp"
    4747#include "Common/utility.h"       // for move, copy
     48#include "Parser/parserutility.h" // for notZeroExpr
    4849#include "SymTab/Mangler.h"
    4950#include "Tuples/Tuples.h"        // for handleTupleAssignment
     
    284285                const CodeLocation & location,
    285286                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,
    287288                unsigned nTuples = 0
    288289        ) {
     
    294295                                // ^^^ need to handle the case where a tuple has a default argument
    295296                                if ( ! instantiateArgument( location,
    296                                         type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;
     297                                        type, nullptr, args, results, genStart, context, nTuples ) ) return false;
    297298                                nTuples = 0;
    298299                        }
     
    509510
    510511                                // 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 ) ) {
    512514                                        // 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                                        //}
    516538                                }
    517539                        }
     
    785807                                        auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>();
    786808                                        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;
    788810                                }
    789811                                goto endMatch;
     
    795817                        // no default args for indirect calls
    796818                        if ( !instantiateArgument( location,
    797                                 param, nullptr, args, results, genStart, symtab ) ) return;
     819                                param, nullptr, args, results, genStart, context ) ) return;
    798820                }
    799821
     
    890912                } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) {
    891913                        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
    950931                }
    951932        }
     
    14141395                        ast::Expr * newExpr = data.combine( nameExpr->location, cost );
    14151396
     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                       
    14161404                        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,
    14181406                                cost );
    14191407
     
    14481436        auto cand = new Candidate(variableExpr, tenv);
    14491437        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         }
    15101438    }
    15111439
     
    15861514        void Finder::postvisit( const ast::LogicalExpr * logicalExpr ) {
    15871515                CandidateFinder finder1( context, tenv );
    1588                 ast::ptr<ast::Expr> arg1 = createCondExpr( logicalExpr->arg1 );
     1516                ast::ptr<ast::Expr> arg1 = notZeroExpr( logicalExpr->arg1 );
    15891517                finder1.find( arg1, ResolveMode::withAdjustment() );
    15901518                if ( finder1.candidates.empty() ) return;
    15911519
    15921520                CandidateFinder finder2( context, tenv );
    1593                 ast::ptr<ast::Expr> arg2 = createCondExpr( logicalExpr->arg2 );
     1521                ast::ptr<ast::Expr> arg2 = notZeroExpr( logicalExpr->arg2 );
    15941522                finder2.find( arg2, ResolveMode::withAdjustment() );
    15951523                if ( finder2.candidates.empty() ) return;
     
    16171545        void Finder::postvisit( const ast::ConditionalExpr * conditionalExpr ) {
    16181546                // candidates for condition
    1619                 ast::ptr<ast::Expr> arg1 = createCondExpr( conditionalExpr->arg1 );
     1547                ast::ptr<ast::Expr> arg1 = notZeroExpr( conditionalExpr->arg1 );
    16201548                CandidateFinder finder1( context, tenv );
    16211549                finder1.find( arg1, ResolveMode::withAdjustment() );
     
    18391767
    18401768                                // 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 );
    18421771                                (void) canUnify;
    18431772                                Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     
    18641793                                        // ambiguous case, still output candidates to print in error message
    18651794                                        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                                }       
    18781830                        }
    18791831                }
     
    19001852                                                std::make_shared<Candidate>(
    19011853                                                        newExpr, copy( tenv ), ast::OpenVarSet{},
    1902                                                         ast::AssertionSet{}, Cost::zero, cost
     1854                                                        ast::AssertionSet{}, Cost::safe, cost
    19031855                                                );
    19041856
     
    22002152}
    22012153
    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
     2155const 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() );
    22162169}
    22172170
Note: See TracChangeset for help on using the changeset viewer.