Changeset af746cc


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

Reimplement the resolution of Enum instance type

Location:
src
Files:
2 added
22 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Decl.cpp

    rd9bad51 raf746cc  
    169169}
    170170
     171const std::string EnumDecl::getUnmangeldArrayName( const ast::EnumAttribute attr ) const {
     172                switch( attr ) {
     173                        case ast::EnumAttribute::Value: return "values_" + name ;
     174                        case ast::EnumAttribute::Label: return "labels_" + name;
     175                        default: /* Posn does not generate array */
     176                                return "";
     177                }
     178        }
     179
    171180}
    172181
  • src/AST/Decl.hpp

    rd9bad51 raf746cc  
    303303};
    304304
     305enum class EnumAttribute{ Value, Posn, Label };
    305306/// enum declaration `enum Foo { ... };`
    306307class EnumDecl final : public AggregateDecl {
     
    326327        const char * typeString() const override { return aggrString( Enum ); }
    327328
    328 
     329        const std::string getUnmangeldArrayName( const EnumAttribute attr ) const;
    329330private:
    330331        EnumDecl * clone() const override { return new EnumDecl{ *this }; }
  • src/AST/Fwd.hpp

    rd9bad51 raf746cc  
    133133class OneType;
    134134class GlobalScopeType;
    135 class EnumPosType;
     135class EnumAttrType;
    136136
    137137class Designation;
  • src/AST/Pass.hpp

    rd9bad51 raf746cc  
    222222        const ast::Type *             visit( const ast::UnionInstType        * ) override final;
    223223        const ast::Type *             visit( const ast::EnumInstType         * ) override final;
    224         const ast::Type *             visit( const ast::EnumPosType          * ) override final;
     224        const ast::Type *             visit( const ast::EnumAttrType         * ) override final;
    225225        const ast::Type *             visit( const ast::TraitInstType        * ) override final;
    226226        const ast::Type *             visit( const ast::TypeInstType         * ) override final;
  • src/AST/Pass.impl.hpp

    rd9bad51 raf746cc  
    19861986
    19871987//--------------------------------------------------------------------------
    1988 // EnumPosType
    1989 template< typename core_t >
    1990 const ast::Type * ast::Pass< core_t >::visit( const ast::EnumPosType * node ) {
    1991         VISIT_START( node );
    1992 
     1988// EnumAttrType
     1989template< typename core_t >
     1990const ast::Type * ast::Pass< core_t >::visit( const ast::EnumAttrType * node ) {
     1991        VISIT_START( node );
    19931992        VISIT_END( Type, node );
    19941993}
  • src/AST/Print.cpp

    rd9bad51 raf746cc  
    15761576        }
    15771577
    1578         virtual const ast::Type * visit( const ast::EnumPosType * node ) override final {
    1579                 preprint( node );
    1580                 os << "enum pos with ";
     1578        virtual const ast::Type * visit( const ast::EnumAttrType * node ) override final {
     1579                preprint( node );
     1580                os << "enum attr ";
     1581        if ( node->attr == ast::EnumAttribute::Label ) {
     1582            os << "Label ";
     1583        } else if ( node->attr == ast::EnumAttribute::Value ) {
     1584            os << "Value ";
     1585        } else {
     1586            os << "Posn ";
     1587        }
    15811588                (*(node->instance)).accept( *this );
    15821589                return node;
  • src/AST/Type.hpp

    rd9bad51 raf746cc  
    362362using EnumInstType = SueInstType<EnumDecl>;
    363363
    364 class EnumPosType final : public Type {
     364class EnumAttrType final : public Type {
    365365public:
    366366        readonly<EnumInstType> instance;
    367         const Type * accept( Visitor & v ) const override { return v.visit( this ); }
    368         EnumPosType( const EnumInstType * instance ): instance(instance) {}
     367    EnumAttribute attr;
     368        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     369        EnumAttrType( const EnumInstType * instance, EnumAttribute attr = EnumAttribute::Posn )
     370                : instance(instance), attr(attr) {}
    369371       
    370 private:
    371         EnumPosType * clone() const override { return new EnumPosType{ *this }; }
     372    bool match( const ast::EnumAttrType * other) const {
     373        return instance->base->name == other->instance->base->name && attr == other->attr;
     374    }
     375private:
     376        EnumAttrType * clone() const override { return new EnumAttrType{ *this }; }
    372377        MUTATE_FRIEND
    373378};
  • src/AST/Visitor.hpp

    rd9bad51 raf746cc  
    119119    virtual const ast::Type *             visit( const ast::OneType              * ) = 0;
    120120    virtual const ast::Type *             visit( const ast::GlobalScopeType      * ) = 0;
    121     virtual const ast::Type *             visit( const ast::EnumPosType          * ) = 0;
     121    virtual const ast::Type *             visit( const ast::EnumAttrType         * ) = 0;
    122122    virtual const ast::Designation *      visit( const ast::Designation          * ) = 0;
    123123    virtual const ast::Init *             visit( const ast::SingleInit           * ) = 0;
  • src/CodeGen/GenType.cc

    rd9bad51 raf746cc  
    4646        void postvisit( ast::UnionInstType const * type );
    4747        void postvisit( ast::EnumInstType const * type );
    48         void postvisit( ast::EnumPosType const * type );
     48        void postvisit( ast::EnumAttrType const * type );
    4949        void postvisit( ast::TypeInstType const * type );
    5050        void postvisit( ast::TupleType const * type );
     
    240240}
    241241
    242 void GenType::postvisit( ast::EnumPosType const * type ) {
     242void GenType::postvisit( ast::EnumAttrType const * type ) {
    243243        postvisit( type->instance );
    244244}
  • src/Common/CodeLocationTools.cpp

    rd9bad51 raf746cc  
    188188    macro(UnionInstType, Type) \
    189189    macro(EnumInstType, Type) \
    190     macro(EnumPosType, Type) \
     190    macro(EnumAttrType, Type) \
    191191    macro(TraitInstType, Type) \
    192192    macro(TypeInstType, Type) \
  • src/GenPoly/Lvalue.cpp

    rd9bad51 raf746cc  
    133133                        return func->linkage == ast::Linkage::Intrinsic
    134134                                && lvalueFunctions.count( func->name );
    135                 }
    136         }
    137         return false;
    138 }
    139 
    140 bool isGeneratedInstrinct( ast::Expr const * expr ) {
    141         if ( auto app = dynamic_cast<ast::ApplicationExpr const *>( expr ) ) {
    142                 if ( app->args.size() == 2 && ast::getFunction( app )->name == "?[?]" ) {
    143                         auto param_1 = dynamic_cast<ast::VariableExpr const *>(app->args.front().get());
    144                         if ( param_1 ) {
    145                                 auto param_1_as_obj = param_1->var.as<ast::ObjectDecl>();
    146                                 return ( param_1_as_obj->name.find( "values_") != std::string::npos
    147                                         ||  param_1_as_obj->name.find( "labels_" ) != std::string::npos );
    148                         }
    149135                }
    150136        }
     
    176162                ast::ApplicationExpr const * expr ) {
    177163
    178         if ( skip == SkipInProgress || !isIntrinsicReference( expr ) || isGeneratedInstrinct( expr ) ) {
     164        if ( skip == SkipInProgress || !isIntrinsicReference( expr ) ) {
    179165                return expr;
    180166        }
  • 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        };
  • src/SymTab/Mangler.cc

    rd9bad51 raf746cc  
    5858        void postvisit( const ast::OneType * oneType );
    5959        void postvisit( const ast::QualifiedType * qualType );
    60 
    61         void postvisit( const ast::EnumPosType * posType );
     60        void postvisit( const ast::EnumAttrType * posType );
    6261
    6362        /// The result is the current constructed mangled name.
     
    281280}
    282281
    283 void Mangler::postvisit( const ast::EnumPosType * pos ) {
    284         postvisit( pos->instance );
    285         mangleName += "_pos";
     282void Mangler::postvisit( const ast::EnumAttrType * enumAttr ) {
     283        postvisit( enumAttr->instance );
     284        // mangleName += "_pos";
     285    switch ( enumAttr->attr )
     286    {
     287        case ast::EnumAttribute::Label:
     288            mangleName += "_label_";
     289            break;
     290        case ast::EnumAttribute::Posn:
     291                        mangleName += "_posn_";
     292            break;
     293        case ast::EnumAttribute::Value:
     294            mangleName += "_value_";
     295            break;
     296    }
     297
    286298}
    287299
  • src/Validate/Autogen.cpp

    rd9bad51 raf746cc  
    196196
    197197        bool shouldAutogen() const final { return true; }
    198         void genAttrFuncForward();
    199         void genPosFunctions();
    200198private:
    201199        void genFuncBody( ast::FunctionDecl * decl ) final;
    202200        void genFieldCtors() final;
    203201        const ast::Decl * getDecl() const final { return decl; }
    204 
    205         ast::FunctionDecl * genPosProto() const;
    206         ast::FunctionDecl * genLabelProto() const;
    207         ast::FunctionDecl * genValueProto() const;
    208         ast::FunctionDecl * genSuccProto() const;
    209         ast::FunctionDecl * genPredProto() const;
    210 
    211         ast::FunctionDecl * genSuccPosProto() const;
    212         ast::FunctionDecl * genPredPosProto() const;
    213 
    214         ast::FunctionDecl * genSuccPredFunc( bool succ );
    215         // ast::FunctionDecl * genPredFunc();
    216202};
    217203
     
    256242        enumInst.base = enumDecl;
    257243        EnumFuncGenerator gen( enumDecl, &enumInst, functionNesting );
    258         if ( enumDecl->base ) {
    259                 gen.genAttrFuncForward();
    260                 gen.genPosFunctions();
    261         }
    262244        gen.generateAndAppendFunctions( declsToAddAfter );
    263245}
     
    418400}
    419401
    420 /// Use the current type T to create `void ?{}(T & _dst)`.
     402/// Use the current type T to create `void ^?{}(T & _dst)`.
    421403ast::FunctionDecl * FuncGenerator::genDtorProto() const {
    422404        // The destructor must be mutex on a concurrent type.
     
    777759}
    778760
    779 ast::FunctionDecl * EnumFuncGenerator::genPosProto() const {
    780         return genProto( "posE",
    781                 { new ast::ObjectDecl( getLocation(), "_i",
    782                 new ast::EnumInstType( decl ) )},
    783                 { new ast::ObjectDecl( getLocation(), "_ret",
    784                 new ast::BasicType{ ast::BasicType::UnsignedInt } )} );
    785 }
    786 
    787 ast::FunctionDecl * EnumFuncGenerator::genLabelProto() const {
    788         return genProto( "labelE",
    789                 { new ast::ObjectDecl( getLocation(), "_i",
    790                 new ast::EnumInstType( decl ) ) },
    791                 { new ast::ObjectDecl( getLocation(), "_ret",
    792                 new ast::PointerType( new ast::BasicType{ ast::BasicType::Char } ) ) } );
    793 }
    794 
    795 ast::FunctionDecl * EnumFuncGenerator::genValueProto() const {
    796         return genProto( "valueE",
    797                 { new ast::ObjectDecl( getLocation(), "_i", new ast::EnumInstType( decl ) )},
    798                 { new ast::ObjectDecl( getLocation(), "_ret", ast::deepCopy( decl->base ) ) } );
    799 }
    800 
    801 ast::FunctionDecl * EnumFuncGenerator::genSuccProto() const {
    802         return genProto( "succ",
    803                 { new ast::ObjectDecl( getLocation(), "_i", new ast::EnumInstType( decl ) )},
    804                 { new ast::ObjectDecl( getLocation(), "_ret", new ast::EnumInstType( decl ))} );
    805 }
    806 
    807 ast::FunctionDecl * EnumFuncGenerator::genPredProto() const {
    808         return genProto( "pred",
    809                 { new ast::ObjectDecl( getLocation(), "_i", new ast::EnumInstType( decl ))},
    810                 { new ast::ObjectDecl( getLocation(), "_ret", new ast::EnumInstType( decl ))} );
    811 }
    812 
    813 ast::FunctionDecl * EnumFuncGenerator::genSuccPosProto() const {
    814         return genProto( "_successor_",
    815                 { new ast::ObjectDecl( getLocation(), "_i",
    816                         new ast::EnumPosType( new ast::EnumInstType( decl ) ) )},
    817                 {
    818                         new ast::ObjectDecl( getLocation(), "_ret",
    819                         new ast::EnumPosType( new ast::EnumInstType( decl ) ) )
    820                 } );
    821 }
    822 
    823 ast::FunctionDecl * EnumFuncGenerator::genPredPosProto() const {
    824         return genProto( "_predessor_",
    825                 { new ast::ObjectDecl( getLocation(), "_i",
    826                         new ast::EnumPosType( new ast::EnumInstType( decl ) ) )},
    827                 {
    828                         new ast::ObjectDecl( getLocation(), "_ret",
    829                         new ast::EnumPosType( new ast::EnumInstType( decl ) ) )
    830                 } );
    831 }
    832 
    833 ast::FunctionDecl * EnumFuncGenerator::genSuccPredFunc( bool succ ) {
    834         ast::FunctionDecl * decl = succ? genSuccPosProto(): genPredPosProto();
    835         produceForwardDecl( decl );
    836 
    837         const CodeLocation& location = getLocation();
    838 
    839         auto & params = decl->params;
    840         assert( params.size() == 1 );
    841         auto param = params.front().strict_as<ast::ObjectDecl>();
    842 
    843         auto newReturn = new ast::ObjectDecl( location, "_returns",
    844                 new ast::BasicType{ ast::BasicType::SignedInt} );
    845        
    846 
    847         ast::UntypedExpr * addOneExpr = new ast::UntypedExpr( location,
    848                 new ast::NameExpr( location, succ? "?+?": "?-?" )
    849         );
    850         addOneExpr->args.push_back(
    851                 new ast::CastExpr( location,
    852                         new ast::VariableExpr( location, param ),
    853                         new ast::BasicType{ ast::BasicType::SignedInt }
    854                 )
    855         );
    856         addOneExpr->args.push_back(
    857                 ast::ConstantExpr::from_int( location, 1 )
    858         );
    859 
    860         ast::UntypedExpr * assignExpr = new ast::UntypedExpr( location,
    861                 new ast::NameExpr( location, "?=?" )
    862         );
    863         assignExpr->args.push_back(     
    864                 new ast::VariableExpr( location, newReturn )
    865         );
    866         assignExpr->args.push_back(
    867                 addOneExpr
    868         );
    869 
    870         decl->stmts = new ast::CompoundStmt( location,
    871                 {
    872                         new ast::DeclStmt( location, newReturn ),
    873                         new ast::ExprStmt( location, assignExpr ),
    874                         new ast::ReturnStmt( location,
    875                                 new ast::VariableExpr( location, newReturn ))
    876                 } );
    877        
    878         return decl;
    879 }
    880 
    881 void EnumFuncGenerator::genAttrFuncForward() { 
    882         if ( decl->base ) {
    883                 ast::FunctionDecl *(EnumFuncGenerator::*attrProtos[5])() const = {
    884                         &EnumFuncGenerator::genPosProto, &EnumFuncGenerator::genLabelProto,
    885                         &EnumFuncGenerator::genValueProto, &EnumFuncGenerator::genSuccProto,
    886                         &EnumFuncGenerator::genPredProto
    887                         // ,&EnumFuncGenerator::genSuccPosProto,
    888                         // &EnumFuncGenerator::genPredPosProto
    889                 };
    890                 for ( auto & generator : attrProtos ) {
    891                         produceForwardDecl( (this->*generator)() );
    892                 }
    893         }
    894 }
    895 
    896 void EnumFuncGenerator::genPosFunctions() {
    897         if ( decl->base ) {
    898                 ast::FunctionDecl * succ = genSuccPredFunc( true );
    899                 ast::FunctionDecl * pred = genSuccPredFunc( false );
    900                 produceDecl( succ );
    901                 produceDecl( pred );
    902         }
    903 
    904 }
    905 
    906761void TypeFuncGenerator::genFieldCtors() {
    907762        // Opaque types do not have field constructors.
  • src/Validate/ReplacePseudoFunc.cpp

    rd9bad51 raf746cc  
    1616
    1717namespace {
    18 
    19 std::set<std::string> queryLabels;
    20 std::set<std::string> queryValues;
    21 
    22 struct ReplaceEnumInstWithPos final : public ast::WithShortCircuiting {
    23     const ast::ObjectDecl* postvisit(const ast::ObjectDecl* decl) {
    24         auto enumInst = decl->type.strict_as<ast::EnumInstType>();
    25         auto enumPos = new ast::EnumPosType(enumInst);
    26         auto ret = ast::mutate_field(decl, &ast::ObjectDecl::type, enumPos);
    27         ret = ast::mutate_field(ret, &ast::ObjectDecl::mangleName,
    28                                 Mangle::mangle(ret));
    29         return ret;
    30     }
    31 };
    32 
    33 const inline std::string getValueArrayName(std::string enumName) {
    34     return "values_" + enumName;
    35 }
    36 
    37 // struct AutoInit {
    38 //     ast::EnumDecl const* postvisit( const ast::EnumDecl* expr );
    39 // };
    40 
    41 struct WrapEnumValueExpr final : public ast::WithShortCircuiting,
    42                                  public ast::WithSymbolTable,
    43                                  public ast::WithConstTranslationUnit {
    44     void previsit(const ast::DeclStmt* expr);
    45     void previsit(const ast::ApplicationExpr* expr);
    46     void previsit(const ast::CastExpr* expr);
    47     void previsit(const ast::VariableExpr*) { visit_children = false; }
    48 
    49     ast::Expr const* postvisit(const ast::VariableExpr* expr);
    50 };
    51 
    52 struct FindGenEnumArray final : public ast::WithShortCircuiting {
    53     void previsit(const ast::ApplicationExpr* enumDecl);
    54 };
    55 
    56 struct PseudoFuncGenerateRoutine final : public ast::WithDeclsToAdd<>,
    57                                          public ast::WithSymbolTable,
    58                                          public ast::WithShortCircuiting,
    59                                          public ast::WithConstTranslationUnit {
    60     void previsit(const ast::EnumDecl* enumDecl);
    61 };
    62 
    63 struct ReplacePseudoFuncCore : public ast::WithShortCircuiting,
    64                                public ast::WithSymbolTable,
    65                                public ast::WithConstTranslationUnit {
    66     ast::Expr const* postvisit(ast::ApplicationExpr const* decl);
    67 };
    68 
    69 // ast::EnumDecl const * AutoInit::postvisit( const ast::EnumDecl * expr ) {
    70 //     for ( size_t i = 0; i < expr->members.size(); i++ ) {
    71 //         auto mem = expr->members[i].as<ast::ObjectDecl>();
    72 //         assert( mem );
    73 //         if ( mem->init )
    74 //     }
    75 //     return expr;
    76 // }
    77 
    78 void WrapEnumValueExpr::previsit(const ast::ApplicationExpr* expr) {
    79     auto varExpr = expr->func.as<ast::VariableExpr>();
    80     auto fname = ast::getFunctionName(expr);
    81     if (!varExpr || varExpr->var->linkage == ast::Linkage::Intrinsic) {
    82         if (fname == "?{}" || fname == "?=?") visit_children = false;
    83     }
    84 
    85     if (fname == "labelE" || fname == "valueE" || fname == "posE" ||
    86         fname == "pred" || fname == "succ") {
    87         visit_children = false;
    88     }
    89 }
    90 
    91 void WrapEnumValueExpr::previsit(const ast::DeclStmt*) {
    92     visit_children = false;
    93 }
    94 
    95 void WrapEnumValueExpr::previsit(const ast::CastExpr* expr) {
    96     if (expr->result && expr->result.as<ast::ReferenceType>()) {
    97         visit_children = false;
    98     }
    99 }
    100 
    101 ast::Expr const* WrapEnumValueExpr::postvisit(const ast::VariableExpr* expr) {
    102     if (!expr->result) {
    103         return expr;
    104     }
    105     if (auto enumInst = expr->result.as<ast::EnumInstType>()) {
    106         if (enumInst->base && enumInst->base->base) {
    107             auto untyped = new ast::UntypedExpr(
    108                 expr->location, new ast::NameExpr(expr->location, "valueE"),
    109                 {std::move(expr)});
    110             ResolvExpr::ResolveContext context{symtab, transUnit().global};
    111             auto result = ResolvExpr::findVoidExpression(untyped, context);
    112             ast::ptr<ast::ApplicationExpr> ret =
    113                 result.strict_as<ast::ApplicationExpr>();
    114             return ast::deepCopy(ret);
    115         }
    116     }
    117     return expr;
    118 }
    119 
    120 void FindGenEnumArray::previsit(const ast::ApplicationExpr* expr) {
    121     auto fname = ast::getFunctionName(expr);
    122     if (fname == "labelE" || fname == "valueE") {
    123         if (expr->args.size() != 1) {
    124             SemanticError(expr, "Position Expression only take one parameter");
    125         }
    126         const ast::VariableExpr* arg =
    127             expr->args.front().as<const ast::VariableExpr>();
    128         if (!arg) {
    129             SemanticError(expr, "Unimplement Pseudo Function Cases");
    130         }
    131         const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();
    132         const std::string referredName = argAsVar->name;
    133         const ast::EnumInstType* argType =
    134             argAsVar->type.as<const ast::EnumInstType>();
    135         if (!argType) {
    136             SemanticError(
    137                 argAsVar,
    138                 "Position can only be used on an enumeration instance");
    139         }
    140         ast::ptr<ast::EnumDecl> base = argType->base;
    141         assert(base);
    142         if (fname == "labelE") queryLabels.insert(base->name);
    143         if (fname == "valueE") queryValues.insert(base->name);
    144     }
    145 }
    146 
    147 const ast::Init* getAutoInit(const CodeLocation& location,
    148                              const ast::Type* type,
    149                              ResolvExpr::ResolveContext context,
    150                              const ast::Init* prev) {
    151     if (auto prevInit = dynamic_cast<const ast::SingleInit*>(prev)) {
    152         auto prevInitExpr = prevInit->value;
    153         if (auto constInit = prevInitExpr.as<ast::ConstantExpr>()) {
    154             // Assume no string literal for now
    155             return new ast::SingleInit(
    156                 location, ast::ConstantExpr::from_int(
    157                               location, constInit->intValue() + 1));
    158         } else {
    159             auto untypedThisInit = new ast::UntypedExpr(
    160                 location, new ast::NameExpr(location, "?++"), {prevInitExpr});
    161             auto typedInit = ResolvExpr::findSingleExpression(untypedThisInit,
    162                                                               type, context);
    163             return new ast::SingleInit(location, typedInit);
    164         }
    165     }
    166     SemanticError(prev, "Auto Init a List is not implemented");
    167     return prev;
    168 }
    169 
    170 void PseudoFuncGenerateRoutine::previsit(const ast::EnumDecl* enumDecl) {
    171     visit_children = false;
    172     const CodeLocation& location = enumDecl->location;
    173     if (enumDecl->members.size() == 0 || !enumDecl->base) return;
    174 
    175     std::vector<ast::ptr<ast::Init>> inits;
    176     std::vector<ast::ptr<ast::Init>> labels;
    177     auto type = enumDecl->base;
    178 
    179     for (size_t i = 0; i < enumDecl->members.size(); i++) {
    180         ast::ptr<ast::Decl> mem = enumDecl->members.at(i);
    181         auto memAsObjectDecl = mem.as<ast::ObjectDecl>();
    182         assert(memAsObjectDecl);
    183         if (memAsObjectDecl->init) {
    184             inits.emplace_back(memAsObjectDecl->init);
    185         } else {
    186             const CodeLocation& location = mem->location;
    187             if (i == 0) {
    188                 inits.emplace_back(new ast::SingleInit(
    189                     location, ast::ConstantExpr::from_int(mem->location, 0)));
    190             } else {
    191                 inits.emplace_back(getAutoInit(
    192                     location, enumDecl->base,
    193                     ResolvExpr::ResolveContext{symtab, transUnit().global},
    194                     inits.at(i - 1).as<ast::SingleInit>()));
    195             }
    196         }
    197         labels.emplace_back(new ast::SingleInit(
    198             location, ast::ConstantExpr::from_string(location, mem->name)));
    199     }
    200     if (queryValues.count(enumDecl->name)) {
    201         auto init = new ast::ListInit(location, std::move(inits));
    202         const ast::ArrayType* arrT = new ast::ArrayType(
    203             enumDecl->base,
    204             ast::ConstantExpr::from_int(location, enumDecl->members.size()),
    205             ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim);
    206         ast::ObjectDecl* values = new ast::ObjectDecl(
    207             location, "values_" + enumDecl->name, arrT, init,
    208             ast::Storage::Static, ast::Linkage::AutoGen);
    209         symtab.addId(values);
    210         values->mangleName = Mangle::mangle(values);
    211         declsToAddAfter.push_back(values);
    212     }
    213     if (queryLabels.count(enumDecl->name)) {
    214         auto label_strings = new ast::ListInit(location, std::move(labels));
    215         auto labels = new ast::ObjectDecl(
    216             location, "labels_" + enumDecl->name,
    217             new ast::ArrayType(
    218                 new ast::PointerType(new ast::BasicType{ast::BasicType::Char}),
    219                 ast::ConstantExpr::from_int(location, enumDecl->members.size()),
    220                 ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim),
    221             label_strings, ast::Storage::Static, ast::Linkage::AutoGen);
    222         symtab.addId(labels);
    223         labels->mangleName = Mangle::mangle(labels);
    224         declsToAddAfter.push_back(labels);
    225     }
    226 }
    227 
    228 ast::ApplicationExpr const* resolveAttributeFunctions(
    229     const CodeLocation location, ResolvExpr::ResolveContext context,
    230     const ast::VariableExpr* arg, const ast::EnumDecl* base,
    231     const std::string& name) {
    232     ast::Expr* toResolve = new ast::NameExpr(location, name + base->name);
    233     // Find the request arrary
    234     auto arr = ResolvExpr::findVoidExpression(toResolve, context);
    235     assert(arr.get());
    236     auto arrAsVar = arr.strict_as<ast::VariableExpr>();
    237     // change EnumInstType to EnumPosType to avoid recursive resolution
    238     auto argAsDecl = arg->var.as<ast::ObjectDecl>();
    239     if (argAsDecl->type.as<ast::EnumInstType>()) {
    240         ast::Pass<ReplaceEnumInstWithPos> replacer;
    241         auto rep = argAsDecl->accept(replacer);
    242         auto mutatedArg = ast::mutate_field(arg, &ast::VariableExpr::var, rep);
    243         mutatedArg = ast::mutate_field(mutatedArg, &ast::VariableExpr::result,
    244                                        mutatedArg->var->get_type());
    245         auto untyped =
    246             new ast::UntypedExpr(location, new ast::NameExpr(location, "?[?]"),
    247                                  {std::move(arrAsVar), mutatedArg});
    248         auto typedResult = ResolvExpr::findVoidExpression(untyped, context);
    249         ast::ptr<ast::ApplicationExpr> ret =
    250             typedResult.strict_as<ast::ApplicationExpr>();
    251         return ast::deepCopy(ret);
    252     } else {
    253         auto untyped =
    254             new ast::UntypedExpr(location, new ast::NameExpr(location, "?[?]"),
    255                                  {std::move(arrAsVar), arg});
    256         auto typedResult = ResolvExpr::findVoidExpression(untyped, context);
    257 
    258         ast::ptr<ast::ApplicationExpr> ret =
    259             typedResult.strict_as<ast::ApplicationExpr>();
    260         return ast::deepCopy(ret);
    261     }
    262 }
    263 
    264 ast::Expr const* ReplacePseudoFuncCore::postvisit(
    265     ast::ApplicationExpr const* expr) {
    266     auto fname = ast::getFunctionName(expr);
    267     auto location = expr->location;
    268     if (fname == "posE" || fname == "valueE" || fname == "labelE") {
    269         if (expr->args.size() != 1) {
    270             SemanticError(expr,
    271                           "Pseudo Enum Expression only take one parameter");
    272         }
    273         ast::ptr<ast::VariableExpr> arg =
    274             expr->args.front().as<const ast::VariableExpr>();
    275         if (!arg) {
    276             SemanticError(expr, "Unimplement Pseudo Function Cases");
    277         }
    278         const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();
    279         const std::string referredName = argAsVar->name;
    280 
    281         if (const ast::EnumInstType* argTypeAsEnumInst =
    282                 argAsVar->type.as<const ast::EnumInstType>()) {
    283             const ast::EnumDecl* base = argTypeAsEnumInst->base;
    284             ResolvExpr::ResolveContext context{symtab, transUnit().global};
    285             // If resolvable as constant
    286             for (size_t i = 0; i < base->members.size(); i++) {
    287                 if (base->members[i]->name == referredName) {
    288                     if (fname == "posE")
    289                         return ast::ConstantExpr::from_int(expr->location, i);
    290                     else if (fname == "labelE")
    291                         return ast::ConstantExpr::from_string(expr->location,
    292                                                               referredName);
    293                     else {
    294                         return resolveAttributeFunctions(
    295                             location, context, arg.get(), base, "values_");
    296                     }
    297                 }
    298             }
    299 
    300             if (fname == "labelE") {
    301                 if (auto labelExpr = resolveAttributeFunctions(
    302                         location, context, arg.get(), base, "labels_")) {
    303                     return labelExpr;
    304                 }
    305             } else if (fname == "valueE") {
    306                 if (auto valueExpr = resolveAttributeFunctions(
    307                         location, context, arg.get(), base, "values_")) {
    308                     return valueExpr;
    309                 }
    310             } else {  // it is position; replace itself
    311                 return std::move(arg.get());
    312             }
    313         } else if (const ast::EnumPosType* argTypeAsPos =
    314                        argAsVar->type.as<const ast::EnumPosType>()) {
    315             const ast::EnumDecl* base = argTypeAsPos->instance->base;
    316             ResolvExpr::ResolveContext context{symtab, transUnit().global};
    317             if (fname == "labelE") {
    318                 if (auto labelExpr = resolveAttributeFunctions(
    319                         location, context, arg.get(), base, "labels_")) {
    320                     return labelExpr;
    321                 }
    322             } else if (fname == "valueE") {
    323                 if (auto valueExpr = resolveAttributeFunctions(
    324                         location, context, arg.get(), base, "values_")) {
    325                     return valueExpr;
    326                 }
    327             } else {  // it is position; replace itself
    328                 return std::move(arg.get());
    329             }
    330         } else {
    331             SemanticError(argAsVar,
    332                           "Pseudo Enum Expression can only be used on an "
    333                           "enumeration instance");
    334         }
    335     }
    336     return expr;
    337 }
    33818
    33919ast::ptr<ast::Expr> reduceCastExpr(ast::ptr<ast::Expr> expr) {
     
    35737                    if (auto enumInst =
    35838                            argAsDecl->type.as<ast::EnumInstType>()) {
    359                         auto castTo = new ast::EnumPosType(enumInst);
     39                        auto castTo = new ast::EnumAttrType(
     40                            enumInst, ast::EnumAttribute::Posn);
    36041                        auto castExpr =
    36142                            new ast::CastExpr(param->location, param, castTo);
     
    37556                        return ast::deepCopy(ret);
    37657                    } else if (auto posType =
    377                                    argAsDecl->type.as<ast::EnumPosType>()) {
    378                         // Very nasty fix. Must be revisit
    379                         if (auto paramAsVar = param.as<ast::VariableExpr>()) {
    380                             if (paramAsVar->result.as<ast::EnumInstType>()) {
    381                                 auto paramToUse = ast::mutate_field(
    382                                     paramAsVar, &ast::VariableExpr::result,
    383                                     posType);
    384                                 auto untyped = new ast::UntypedExpr(
    385                                     expr->location,
    386                                     new ast::NameExpr(location,
    387                                                       fname == "succ"
    388                                                           ? "_successor_"
    389                                                           : "_predessor_"),
    390                                     {paramToUse});
    391                                 ResolvExpr::ResolveContext context{
    392                                     symtab, transUnit().global};
    393                                 auto typedResult =
    394                                     ResolvExpr::findVoidExpression(untyped,
    395                                                                    context);
    396                                 ast::ptr<ast::ApplicationExpr> ret =
    397                                     typedResult
    398                                         .strict_as<ast::ApplicationExpr>();
    399                                 return ast::deepCopy(ret);
    400                             }
    401                         }
    402                         auto untyped = new ast::UntypedExpr(
    403                             expr->location,
    404                             new ast::NameExpr(location, fname == "succ"
    405                                                             ? "_successor_"
    406                                                             : "_predessor_"),
    407                             {param});
    408                         ResolvExpr::ResolveContext context{symtab,
    409                                                            transUnit().global};
    410                         auto typedResult =
    411                             ResolvExpr::findVoidExpression(untyped, context);
    412                         ast::ptr<ast::ApplicationExpr> ret =
    413                             typedResult.strict_as<ast::ApplicationExpr>();
    414                         return ast::deepCopy(ret);
     58                                   argAsDecl->type.as<ast::EnumAttrType>()) {
     59                        std::cerr << "PseudoFunc: succ/pred should not be applied on EnumAttrType directly" << std::endl;
    41560                    }
    41661                }
     
    42469
    42570void replacePseudoFunc(ast::TranslationUnit& translationUnit) {
    426     ast::Pass<WrapEnumValueExpr>::run(translationUnit);
    427     ast::Pass<FindGenEnumArray>::run(translationUnit);
    428 
    429     ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit);
    430     ast::Pass<ReplacePseudoFuncCore>::run(translationUnit);
    431 
    43271    ast::Pass<ReplaceSuccAndPred>::run(translationUnit);
    43372}
  • src/Validate/module.mk

    rd9bad51 raf746cc  
    5454        Validate/VerifyCtorDtorAssign.hpp \
    5555        Validate/ReplacePseudoFunc.cpp \
    56         Validate/ReplacePseudoFunc.hpp
     56        Validate/ReplacePseudoFunc.hpp \
     57        Validate/ImplementEnumFunc.cpp \
     58        Validate/ImplementEnumFunc.hpp
    5759
    5860SRCDEMANGLE += $(SRC_VALIDATE)
  • src/main.cc

    rd9bad51 raf746cc  
    6666#include "Tuples/Tuples.h"                  // for expandMemberTuples, expan...
    6767#include "Validate/Autogen.hpp"             // for autogenerateRoutines
    68 // #include "Validate/ImplementEnumFunc.hpp"   // for implementEnumFunc
     68#include "Validate/ImplementEnumFunc.hpp"   // for implementEnumFunc
    6969#include "Validate/CompoundLiteral.hpp"     // for handleCompoundLiterals
    7070#include "Validate/EliminateTypedef.hpp"    // for eliminateTypedef
     
    333333
    334334                PASS( "Generate Autogen Routines", Validate::autogenerateRoutines, transUnit );
    335                 // PASS( "Generate Enum Attributes Functions", Validate::implementEnumFunc, transUnit );
     335                PASS( "Generate Enum Attributes Functions", Validate::implementEnumFunc, transUnit );
    336336
    337337                PASS( "Implement Actors", Concurrency::implementActors, transUnit );
     
    383383                PASS( "Replace Pseudo Func", Validate::replacePseudoFunc, transUnit );
    384384                DUMP( reppseu, std::move( transUnit ) );
    385                 PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() );
     385                PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() ); // Here
    386386                PASS( "Erase With", ResolvExpr::eraseWith, transUnit );
    387387
Note: See TracChangeset for help on using the changeset viewer.