Changeset af746cc for src/ResolvExpr


Ignore:
Timestamp:
Apr 15, 2024, 12:03:53 PM (8 months ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
dc58e5d
Parents:
d9bad51
Message:

Reimplement the resolution of Enum instance type

Location:
src/ResolvExpr
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CandidateFinder.cpp

    rd9bad51 raf746cc  
    285285                const CodeLocation & location,
    286286                const ast::Type * paramType, const ast::Init * init, const ExplodedArgs & args,
    287                 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,
     287                std::vector< ArgPack > & results, std::size_t & genStart, const ResolveContext & context,
    288288                unsigned nTuples = 0
    289289        ) {
     
    295295                                // ^^^ need to handle the case where a tuple has a default argument
    296296                                if ( ! instantiateArgument( location,
    297                                         type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;
     297                                        type, nullptr, args, results, genStart, context, nTuples ) ) return false;
    298298                                nTuples = 0;
    299299                        }
     
    510510
    511511                                // attempt to unify types
    512                                 if ( unify( paramType, argType, env, need, have, open ) ) {
     512                                ast::ptr<ast::Type> common;
     513                                if ( unify( paramType, argType, env, need, have, open, common ) ) {
    513514                                        // add new result
    514                                         results.emplace_back(
    515                                                 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ),
    516                                                 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                                        //}
    517538                                }
    518539                        }
     
    786807                                        auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>();
    787808                                        if ( !instantiateArgument( location,
    788                                                 funcType->params[i], obj->init, args, results, genStart, symtab)) return;
     809                                                funcType->params[i], obj->init, args, results, genStart, context)) return;
    789810                                }
    790811                                goto endMatch;
     
    796817                        // no default args for indirect calls
    797818                        if ( !instantiateArgument( location,
    798                                 param, nullptr, args, results, genStart, symtab ) ) return;
     819                                param, nullptr, args, results, genStart, context ) ) return;
    799820                }
    800821
     
    891912                } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) {
    892913                        addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" );
    893                 }
    894                 else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) {
    895                         if (enumInst->base && enumInst->base->base) {
    896             const CodeLocation &location = cand->expr->location;
    897 
    898             CandidateFinder funcFinder(context, tenv);
    899             auto nameExpr = new ast::NameExpr(location, "valueE");
    900             ResolveMode mode = {true, false, selfFinder.candidates.empty()};
    901             funcFinder.find( nameExpr, mode );
    902 
    903             // make variableExpr itself the candidate for the value Call
    904             ExplodedArgs argExpansions;
    905             argExpansions.emplace_back();
    906             auto &argE = argExpansions.back();
    907 
    908             argE.emplace_back(*cand, symtab); // Use the typed name expr as param for value
    909 
    910             CandidateList found;
    911             SemanticErrorException errors;
    912 
    913             for (CandidateRef &func : funcFinder) {
    914                 try {
    915                     const ast::Type *funcResult =
    916                         func->expr->result->stripReferences();
    917                     if (auto pointer = dynamic_cast<const ast::PointerType *>(
    918                             funcResult)) {
    919                         if (auto function =
    920                                 pointer->base.as<ast::FunctionType>()) {
    921                             CandidateRef newFunc{new Candidate{*func}};
    922                             newFunc->expr = referenceToRvalueConversion(
    923                                 newFunc->expr, newFunc->cost);
    924                             makeFunctionCandidates( location,
    925                                                    newFunc, function,
    926                                                    argExpansions, found );
    927                         }
    928                     }
    929                 } catch (SemanticErrorException &e) {
    930                     std::cerr
    931                         << "Resolving value function should cause an error"
    932                         << std::endl;
    933                     errors.append(e);
    934                 }
    935             }
    936 
    937             if (found.empty()) {
    938                 std::cerr << "Resolve value function should always success"
    939                           << std::endl;
    940             }
    941 
    942             for (CandidateRef &withFunc : found) {
    943                 withFunc->cost.incSafe();
    944                 Cost cvtCost =
    945                     computeApplicationConversionCost(withFunc, symtab);
    946                 assert(cvtCost != Cost::infinity);
    947 
    948                 candidates.emplace_back(std::move(withFunc));
    949             }
    950         }
     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
    951931                }
    952932        }
     
    14151395                        ast::Expr * newExpr = data.combine( nameExpr->location, cost );
    14161396
     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                       
    14171404                        CandidateRef newCand = std::make_shared<Candidate>(
    1418                                 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
     1405                                newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, bentConversion? Cost::safe: Cost::zero,
    14191406                                cost );
    14201407
     
    14491436        auto cand = new Candidate(variableExpr, tenv);
    14501437        candidates.emplace_back(cand);
    1451 
    1452         if (auto enumInst = dynamic_cast<const ast::EnumInstType *>(
    1453                 variableExpr->var->get_type())) {
    1454             if (enumInst->base && enumInst->base->base) {
    1455                 const CodeLocation &location = cand->expr->location;
    1456 
    1457                 CandidateFinder funcFinder(context, tenv);
    1458                 auto nameExpr = new ast::NameExpr(location, "valueE");
    1459                 ResolveMode mode = {true, false, selfFinder.candidates.empty()};
    1460                 funcFinder.find( nameExpr, mode );
    1461 
    1462                 // make variableExpr itself the candidate for the value Call
    1463                 ExplodedArgs argExpansions;
    1464                 argExpansions.emplace_back();
    1465                 auto &argE = argExpansions.back();
    1466 
    1467                 argE.emplace_back(*cand, symtab);
    1468 
    1469                 CandidateList found;
    1470                 SemanticErrorException errors;
    1471 
    1472                 for (CandidateRef &func : funcFinder) {
    1473                     try {
    1474                     const ast::Type *funcResult =
    1475                         func->expr->result->stripReferences();
    1476                     if (auto pointer = dynamic_cast<const ast::PointerType *>(
    1477                             funcResult)) {
    1478                         if (auto function =
    1479                                 pointer->base.as<ast::FunctionType>()) {
    1480                             CandidateRef newFunc{new Candidate{*func}};
    1481                             newFunc->expr = referenceToRvalueConversion(
    1482                                 newFunc->expr, newFunc->cost);
    1483                             makeFunctionCandidates(variableExpr->location,
    1484                                                    newFunc, function,
    1485                                                    argExpansions, found);
    1486                         }
    1487                     }
    1488                     } catch (SemanticErrorException &e) {
    1489                         std::cerr
    1490                             << "Resolving value function should cause an error"
    1491                             << std::endl;
    1492                         errors.append(e);
    1493                     }
    1494                 }
    1495 
    1496                 if (found.empty()) {
    1497                     std::cerr << "Resolve value function should always success"
    1498                             << std::endl;
    1499                 }
    1500 
    1501                 for (CandidateRef &withFunc : found) {
    1502                     withFunc->cost.incSafe();
    1503                     Cost cvtCost =
    1504                         computeApplicationConversionCost(withFunc, symtab);
    1505                     assert(cvtCost != Cost::infinity);
    1506 
    1507                     candidates.emplace_back(std::move(withFunc));
    1508                 }
    1509             }
    1510         }
    15111438    }
    15121439
     
    18401767
    18411768                                // unification run for side-effects
    1842                                 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 );
    18431771                                (void) canUnify;
    18441772                                Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     
    18651793                                        // ambiguous case, still output candidates to print in error message
    18661794                                        if ( cand->cost == minExprCost && thisCost == minCastCost ) {
    1867                                                 CandidateRef newCand = std::make_shared<Candidate>(
    1868                                                         new ast::InitExpr{
    1869                                                                 initExpr->location,
    1870                                                                 restructureCast( cand->expr, toType ),
    1871                                                                 initAlt.designation },
    1872                                                         std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost );
    1873                                                 // currently assertions are always resolved immediately so this should have no effect.
    1874                                                 // if this somehow changes in the future (e.g. delayed by indeterminate return type)
    1875                                                 // we may need to revisit the logic.
    1876                                                 inferParameters( newCand, matches );
    1877                                         }
    1878                                 }
     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                                }       
    18791830                        }
    18801831                }
     
    19011852                                                std::make_shared<Candidate>(
    19021853                                                        newExpr, copy( tenv ), ast::OpenVarSet{},
    1903                                                         ast::AssertionSet{}, Cost::zero, cost
     1854                                                        ast::AssertionSet{}, Cost::safe, cost
    19041855                                                );
    19051856
     
    22012152}
    22022153
     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() );
     2169}
     2170
    22032171} // namespace ResolvExpr
    22042172
  • src/ResolvExpr/CandidateFinder.hpp

    rd9bad51 raf746cc  
    7070        const ast::Expr * expr, Cost & cost );
    7171
     72const ast::Expr * getValueEnumCall(const ast::Expr * expr,
     73        const ResolvExpr::ResolveContext & context, const ast::TypeEnvironment & env );
     74
    7275} // namespace ResolvExpr
    7376
  • src/ResolvExpr/CommonType.cc

    rd9bad51 raf746cc  
    385385                } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) {
    386386                        const ast::EnumDecl* enumDecl = enumInst->base;
    387                         if ( enumDecl->base ) {
    388                                 result = enumDecl->base.get();
    389                         } else {
     387                        if ( !enumDecl->base ) {
    390388                                ast::BasicType::Kind kind = commonTypes[ basic->kind ][ ast::BasicType::SignedInt ];
    391389                                if (
     
    398396                                }
    399397                        }
    400                 } else if ( dynamic_cast< const ast::EnumPosType * >( type2 ) ) {
    401                         ast::BasicType::Kind kind = commonTypes[ basic->kind ][ ast::BasicType::SignedInt ];
    402                         if (
    403                                 ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers )
    404                                         || widen.first )
    405                                 && ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers )
    406                                         || widen.second )
    407                         ) {
    408                                 result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers };
    409                         }
     398                } else if ( auto type2AsAttr = dynamic_cast< const ast::EnumAttrType * >( type2 ) ) {
     399            if ( type2AsAttr->attr == ast::EnumAttribute::Posn ) {
     400                            ast::BasicType::Kind kind = commonTypes[ basic->kind ][ ast::BasicType::SignedInt ];
     401                            if (
     402                                    ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers )
     403                                            || widen.first )
     404                                    && ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers )
     405                                            || widen.second )
     406                            ) {
     407                                    result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers };
     408                            }
     409            }
    410410                }
    411411        }
     
    426426                result = voidPtr;
    427427                add_qualifiers( result, oPtr->qualifiers );
    428         }
    429 
    430         // For a typed enum, we want to unify type1 with the base type of the enum
    431         bool tryResolveWithTypedEnum( const ast::Type * type1 ) {
    432                 if (auto enumInst = dynamic_cast<const ast::EnumInstType *> (type2) ) {
    433                         ast::OpenVarSet newOpen{ open };
    434                         if (enumInst->base->base
    435                                 && unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen)) {
    436                                         result = type1;
    437                                 return true;
    438                         }
    439                 }
    440                 return false;
    441428        }
    442429
     
    607594                        result = pointer;
    608595                        add_qualifiers( result, type2->qualifiers );
    609                 } else {
    610                         tryResolveWithTypedEnum( pointer );
    611                 }
    612         }
    613 
    614         void postvisit( const ast::ArrayType * arr ) {
    615                 // xxx - does it make sense?
    616                 tryResolveWithTypedEnum( arr );
    617         }
     596                }
     597        }
     598
     599        void postvisit( const ast::ArrayType * arr ) {}
    618600
    619601        void postvisit( const ast::ReferenceType * ref ) {
     
    659641        }
    660642
    661         void postvisit( const ast::FunctionType * func) {
    662                 tryResolveWithTypedEnum( func );
    663         }
    664 
    665         void postvisit( const ast::StructInstType * inst ) {
    666                 tryResolveWithTypedEnum( inst );
    667         }
    668 
    669         void postvisit( const ast::UnionInstType * inst ) {
    670                 tryResolveWithTypedEnum( inst );
    671         }
     643        void postvisit( const ast::FunctionType * func) {}
     644
     645        void postvisit( const ast::StructInstType * inst ) {}
     646
     647        void postvisit( const ast::UnionInstType * inst ) {}
    672648
    673649        void postvisit( const ast::EnumInstType * enumInst ) {
    674                 // if ( dynamic_cast<const ast::EnumPosType *>(enumInst) ) {
    675                 //      result = enumInst;
    676                 // } else
    677                 if (!dynamic_cast<const ast::EnumInstType *>(type2)) {
    678                         result = commonType( type2, enumInst, tenv, need, have, open, widen);
    679                 }
    680         }
    681 
    682         void postvisit( const ast::EnumPosType * enumPos ) {
    683                 if ( auto type2AsPos = dynamic_cast<const ast::EnumPosType *>(type2) ) {
    684                         // result = commonType( type2AsPos->instance, enumPos->instance, tenv, need, have, open, widen );
    685                         // result = enumPos;
    686                         if ( enumPos->instance->base->name == type2AsPos->instance->base->name ) {
    687                                 result = type2;
    688                         }
    689                 } else if ( dynamic_cast<const ast::BasicType *>(type2) ) {
    690                         result = type2;
    691                 }
    692         }
     650                if ( enumInst->base && !enumInst->base->base ) {
     651                        auto basicType = new ast::BasicType( ast::BasicType::UnsignedInt );
     652                        result = commonType( basicType, type2, tenv, need, have, open, widen);
     653                }
     654        }
     655
     656        void postvisit( const ast::EnumAttrType * ) {}
    693657
    694658        void postvisit( const ast::TraitInstType * ) {}
     
    696660        void postvisit( const ast::TypeInstType * ) {}
    697661
    698         void postvisit( const ast::TupleType * tuple ) {
    699                 tryResolveWithTypedEnum( tuple );
    700         }
     662        void postvisit( const ast::TupleType * tuple ) {}
    701663
    702664        void postvisit( const ast::VarArgsType * ) {}
     
    715677                } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) {
    716678                        const ast::EnumDecl * enumDecl = enumInst->base;
    717                         if ( enumDecl->base ) {
    718                                 if ( tryResolveWithTypedEnum( zero ) )
    719                                         add_qualifiers( result, zero->qualifiers );
    720                         } else {
     679                        if ( !enumDecl->base ) {
    721680                                if ( widen.second || zero->qualifiers <= type2->qualifiers ) {
    722681                                        result = type2;
     
    738697                                ast::BasicType::SignedInt, one->qualifiers | type2->qualifiers };
    739698                } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) {
    740                         const ast::EnumDecl * enumBase = enumInst->base;
    741                         if ( enumBase->base ) {
    742                                 if ( tryResolveWithTypedEnum( one ))
    743                                         add_qualifiers( result, one->qualifiers );
    744                         } else {
     699                        const ast::EnumDecl * enumDecl = enumInst->base;
     700                        if ( !enumDecl->base ) {
    745701                                if ( widen.second || one->qualifiers <= type2->qualifiers ) {
    746702                                        result = type2;
  • src/ResolvExpr/ConversionCost.cc

    rd9bad51 raf746cc  
    278278        if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
    279279                conversionCostFromBasicToBasic( basicType, dstAsBasic );
    280         }
    281         else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
    282                 auto enumDecl = enumInst->base;
    283                 if ( enumDecl->base.get() ) {
    284                         // cost = costCalc( basicType, baseType, srcIsLvalue, symtab, env );
    285                         // cost.incUnsafe();
    286                         cost = Cost::infinity;
    287                 } else {
    288             cost = Cost::unsafe;
    289                 }
    290         } else if ( dynamic_cast< const ast::EnumPosType *>(dst) ) {
     280        } else if ( dynamic_cast< const ast::EnumAttrType *>(dst) ) {
    291281                static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
    292282                cost = costCalc( basicType, integer, srcIsLvalue, symtab, env );
     283        } else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
     284                if ( dstAsEnumInst->base && !dstAsEnumInst->base->base ) {
     285                        cost = Cost::zero;
     286                        cost.incUnsafe();
     287                }
    293288        }
    294289}
     
    366361}
    367362
    368 void ConversionCost::postvisit( const ast::EnumInstType * ) {
     363void ConversionCost::postvisit( const ast::EnumInstType * inst ) {
     364        if ( inst->base && inst->base->base ) {
     365                if ( auto dstAsAttr = dynamic_cast<const ast::EnumAttrType *>( dst ) ) {
     366                        auto instAsAttr = ast::EnumAttrType( inst, dstAsAttr->attr );
     367                        if ( instAsAttr.match(dstAsAttr) ) {
     368                                cost.incUnsafe();
     369                        }
     370
     371                } else if ( auto dstAsInst = dynamic_cast<const ast::EnumInstType *>( dst ) ) {
     372                        if (inst->base && dstAsInst->base) {
     373                                if (inst->base == dstAsInst->base) {
     374                                        cost.incUnsafe();
     375                                }
     376                        }
     377                } else {
     378                        auto instAsVal = ast::EnumAttrType( inst, ast::EnumAttribute::Value );
     379                        cost = costCalc( &instAsVal, dst, srcIsLvalue, symtab, env );
     380                        if ( cost < Cost::infinity ) {
     381                                cost.incUnsafe();
     382                        }
     383                }
     384                return;
     385        }
    369386        static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
    370387        cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
     
    374391}
    375392
    376 void ConversionCost::postvisit( const ast::EnumPosType * src ) {
    377         if ( dynamic_cast<const ast::EnumPosType *>( dst ) ) {
    378                 // cost = costCalc( src->instance, dstBase->instance, srcIsLvalue, symtab, env );
    379                 // if ( cost < Cost::unsafe ) cost.incSafe();
    380                 cost = Cost::zero;
    381         } else if ( auto dstBase = dynamic_cast<const ast::EnumInstType *>( dst ) ) {
    382                 cost = costCalc( src->instance, dstBase, srcIsLvalue, symtab, env );
    383                 if ( cost < Cost::unsafe ) cost.incSafe();
    384         } else {
    385                 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
    386                 cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
    387                 if ( cost < Cost::unsafe ) {
    388                         cost.incSafe();
    389                 }
    390         }
    391 
     393void ConversionCost::postvisit( const ast::EnumAttrType * src ) {
     394    auto dstAsEnumAttrType = dynamic_cast<const ast::EnumAttrType *>(dst);
     395    if ( src->attr == ast::EnumAttribute::Label ) {
     396        if ( dstAsEnumAttrType && dstAsEnumAttrType->attr == ast::EnumAttribute::Label ) {
     397            cost = costCalc( src->instance, dstAsEnumAttrType->instance, srcIsLvalue, symtab, env );
     398        }
     399        // Add Conversion To String
     400    } else if ( src->attr == ast::EnumAttribute::Value ) {
     401        if ( dstAsEnumAttrType && dstAsEnumAttrType->attr == ast::EnumAttribute::Value) {
     402            cost = costCalc( src->instance, dstAsEnumAttrType->instance, srcIsLvalue, symtab, env );
     403        } else {
     404            auto baseType = src->instance->base->base;
     405            cost = costCalc( baseType, dst, srcIsLvalue, symtab, env );
     406                        if ( cost < Cost::infinity ) {
     407                                cost.incUnsafe();
     408                        }
     409        }
     410    } else { // ast::EnumAttribute::Posn
     411        if ( auto dstBase = dynamic_cast<const ast::EnumInstType *>( dst ) ) {
     412                    cost = costCalc( src->instance, dstBase, srcIsLvalue, symtab, env );
     413                    if ( cost < Cost::unsafe ) cost.incSafe();
     414            } else {
     415                    static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
     416                    cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
     417                    if ( cost < Cost::unsafe ) {
     418                            cost.incSafe();
     419                    }
     420            }
     421    }
    392422}
    393423
     
    466496                cost.incSafe( maxIntCost + 2 );
    467497                // assuming 0p is supposed to be used for pointers?
     498        } else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
     499                if ( dstAsEnumInst->base && !dstAsEnumInst->base->base ) {
     500                        cost = Cost::zero;
     501                        cost.incUnsafe();
     502                }
    468503        }
    469504}
     
    483518                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    484519                }
     520        } else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
     521                if ( dstAsEnumInst->base && !dstAsEnumInst->base->base ) {
     522                        cost = Cost::zero;
     523                        cost.incUnsafe();
     524                }
    485525        }
    486526}
  • src/ResolvExpr/ConversionCost.h

    rd9bad51 raf746cc  
    7272        void postvisit( const ast::ZeroType * zeroType );
    7373        void postvisit( const ast::OneType * oneType );
    74         void postvisit( const ast::EnumPosType * posType );
     74        void postvisit( const ast::EnumAttrType * posType );
    7575private:
    7676        // refactor for code resue
  • src/ResolvExpr/Unify.cc

    rd9bad51 raf746cc  
    274274                void previsit( const ast::Node * ) { visit_children = false; }
    275275
    276                 void postvisit( const ast::VoidType * ) {
    277                         result = dynamic_cast< const ast::VoidType * >( type2 );
     276                void postvisit( const ast::VoidType * vt) {
     277                        result = dynamic_cast< const ast::VoidType * >( type2 )
     278                                || tryToUnifyWithEnumValue(vt, type2, tenv, need, have, open, noWiden());
     279                        ;
    278280                }
    279281
     
    282284                                result = basic->kind == basic2->kind;
    283285                        }
     286                        result = result || tryToUnifyWithEnumValue(basic, type2, tenv, need, have, open, noWiden());
    284287                }
    285288
     
    290293                                        noWiden());
    291294                        }
     295                        result = result || tryToUnifyWithEnumValue(pointer, type2, tenv, need, have, open, noWiden());
    292296                }
    293297
     
    307311
    308312                        result = unifyExact(
    309                                 array->base, array2->base, tenv, need, have, open, noWiden());
     313                                array->base, array2->base, tenv, need, have, open, noWiden())
     314                                || tryToUnifyWithEnumValue(array, type2, tenv, need, have, open, noWiden());
    310315                }
    311316
     
    399404                }
    400405
     406                bool tryToUnifyWithEnumValue( const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
     407                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     408                        WidenMode widen) {
     409                        if ( auto attrType2 = dynamic_cast<const ast::EnumAttrType *>(type2)) {
     410                                if (attrType2->attr == ast::EnumAttribute::Value) {
     411                                        return unifyExact( type1, attrType2->instance->base->base, env, need, have, open,
     412                                                widen);
     413                                } else if (attrType2->attr == ast::EnumAttribute::Posn) {
     414                                        return unifyExact( type1, attrType2->instance, env, need, have, open, widen );
     415                                }
     416                        }
     417                        return false;
     418                }
     419
    401420        public:
    402421                void postvisit( const ast::FunctionType * func ) {
     
    507526                void postvisit( const ast::StructInstType * aggrType ) {
    508527                        handleGenericRefType( aggrType, type2 );
     528                        result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
    509529                }
    510530
    511531                void postvisit( const ast::UnionInstType * aggrType ) {
    512532                        handleGenericRefType( aggrType, type2 );
     533                        result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
    513534                }
    514535
    515536                void postvisit( const ast::EnumInstType * aggrType ) {
    516537                        handleRefType( aggrType, type2 );
    517                 }
    518 
    519                 void postvisit( const ast::EnumPosType * posType ) {
     538                        result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
     539                }
     540
     541                void postvisit( const ast::EnumAttrType * enumAttr ) {
    520542                        // Lazy approach for now
    521                         auto otherPos = dynamic_cast< const ast::EnumPosType *>(type2);
    522                         if ( otherPos ) {
    523                                 if ( otherPos->instance->base->name == posType->instance->base->name )
    524                                         result = otherPos;
    525                         }
     543                        if ( auto otherPos = dynamic_cast< const ast::EnumAttrType *>(type2) ) {
     544                            if ( enumAttr->match(otherPos) ) {
     545                                    result = otherPos;
     546                            }
     547            } 
    526548                }
    527549
    528550                void postvisit( const ast::TraitInstType * aggrType ) {
    529551                        handleRefType( aggrType, type2 );
     552                        result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
    530553                }
    531554
     
    536559                                this->result = otherInst;
    537560                        }
     561                        result = result || tryToUnifyWithEnumValue(typeInst, type2, tenv, need, have, open, noWiden());
    538562                }
    539563
     
    610634                        auto types2 = flatten( flat2 );
    611635
    612                         result = unifyList( types, types2, tenv, need, have, open );
    613                 }
    614 
    615                 void postvisit( const ast::VarArgsType * ) {
    616                         result = dynamic_cast< const ast::VarArgsType * >( type2 );
    617                 }
    618 
    619                 void postvisit( const ast::ZeroType * ) {
    620                         result = dynamic_cast< const ast::ZeroType * >( type2 );
    621                 }
    622 
    623                 void postvisit( const ast::OneType * ) {
    624                         result = dynamic_cast< const ast::OneType * >( type2 );
     636                        result = unifyList( types, types2, tenv, need, have, open )
     637                                || tryToUnifyWithEnumValue(tuple, type2, tenv, need, have, open, noWiden());
     638                }
     639
     640                void postvisit( const ast::VarArgsType * vat) {
     641                        result = dynamic_cast< const ast::VarArgsType * >( type2 )
     642                                || tryToUnifyWithEnumValue(vat, type2, tenv, need, have, open, noWiden());
     643                }
     644
     645                void postvisit( const ast::ZeroType * zt) {
     646                        result = dynamic_cast< const ast::ZeroType * >( type2 )
     647                                || tryToUnifyWithEnumValue(zt, type2, tenv, need, have, open, noWiden());
     648                }
     649
     650                void postvisit( const ast::OneType * ot) {
     651                        result = dynamic_cast< const ast::OneType * >( type2 )
     652                                || tryToUnifyWithEnumValue(ot, type2, tenv, need, have, open, noWiden());
    625653                }
    626654        };
Note: See TracChangeset for help on using the changeset viewer.