Changes in / [dc58e5d:7a36848]


Ignore:
Location:
src
Files:
2 deleted
22 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Decl.cpp

    rdc58e5d r7a36848  
    169169}
    170170
    171 const 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 
    180171}
    181172
  • src/AST/Decl.hpp

    rdc58e5d r7a36848  
    303303};
    304304
    305 enum class EnumAttribute{ Value, Posn, Label };
    306305/// enum declaration `enum Foo { ... };`
    307306class EnumDecl final : public AggregateDecl {
     
    327326        const char * typeString() const override { return aggrString( Enum ); }
    328327
    329         const std::string getUnmangeldArrayName( const EnumAttribute attr ) const;
     328
    330329private:
    331330        EnumDecl * clone() const override { return new EnumDecl{ *this }; }
  • src/AST/Fwd.hpp

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

    rdc58e5d r7a36848  
    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::EnumAttrType         * ) override final;
     224        const ast::Type *             visit( const ast::EnumPosType          * ) 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

    rdc58e5d r7a36848  
    19401940
    19411941//--------------------------------------------------------------------------
    1942 // EnumAttrType
    1943 template< typename core_t >
    1944 const ast::Type * ast::Pass< core_t >::visit( const ast::EnumAttrType * node ) {
    1945         VISIT_START( node );
     1942// EnumPosType
     1943template< typename core_t >
     1944const ast::Type * ast::Pass< core_t >::visit( const ast::EnumPosType * node ) {
     1945        VISIT_START( node );
     1946
    19461947        VISIT_END( Type, node );
    19471948}
  • src/AST/Print.cpp

    rdc58e5d r7a36848  
    15761576        }
    15771577
    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         }
     1578        virtual const ast::Type * visit( const ast::EnumPosType * node ) override final {
     1579                preprint( node );
     1580                os << "enum pos with ";
    15881581                (*(node->instance)).accept( *this );
    15891582                return node;
  • src/AST/Type.hpp

    rdc58e5d r7a36848  
    362362using EnumInstType = SueInstType<EnumDecl>;
    363363
    364 class EnumAttrType final : public Type {
     364class EnumPosType final : public Type {
    365365public:
    366366        readonly<EnumInstType> 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) {}
     367        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     368        EnumPosType( const EnumInstType * instance ): instance(instance) {}
    371369       
    372     bool match( const ast::EnumAttrType * other) const {
    373         return instance->base->name == other->instance->base->name && attr == other->attr;
    374     }
    375 private:
    376         EnumAttrType * clone() const override { return new EnumAttrType{ *this }; }
     370private:
     371        EnumPosType * clone() const override { return new EnumPosType{ *this }; }
    377372        MUTATE_FRIEND
    378373};
  • src/AST/Visitor.hpp

    rdc58e5d r7a36848  
    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::EnumAttrType         * ) = 0;
     121    virtual const ast::Type *             visit( const ast::EnumPosType          * ) = 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

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

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

    rdc58e5d r7a36848  
    133133                        return func->linkage == ast::Linkage::Intrinsic
    134134                                && lvalueFunctions.count( func->name );
     135                }
     136        }
     137        return false;
     138}
     139
     140bool 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                        }
    135149                }
    136150        }
     
    162176                ast::ApplicationExpr const * expr ) {
    163177
    164         if ( skip == SkipInProgress || !isIntrinsicReference( expr ) ) {
     178        if ( skip == SkipInProgress || !isIntrinsicReference( expr ) || isGeneratedInstrinct( expr ) ) {
    165179                return expr;
    166180        }
  • src/ResolvExpr/CandidateFinder.cpp

    rdc58e5d r7a36848  
    284284                const CodeLocation & location,
    285285                const ast::Type * paramType, const ast::Init * init, const ExplodedArgs & args,
    286                 std::vector< ArgPack > & results, std::size_t & genStart, const ResolveContext & context,
     286                std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,
    287287                unsigned nTuples = 0
    288288        ) {
     
    294294                                // ^^^ need to handle the case where a tuple has a default argument
    295295                                if ( ! instantiateArgument( location,
    296                                         type, nullptr, args, results, genStart, context, nTuples ) ) return false;
     296                                        type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;
    297297                                nTuples = 0;
    298298                        }
     
    509509
    510510                                // attempt to unify types
    511                                 ast::ptr<ast::Type> common;
    512                                 if ( unify( paramType, argType, env, need, have, open, common ) ) {
     511                                if ( unify( paramType, argType, env, need, have, open ) ) {
    513512                                        // add new result
    514                                         assert( common );
    515                                         // auto attrType = common.as<ast::EnumAttrType>();
    516                                         // if ( attrType && ( attrType->attr == ast::EnumAttribute::Value ) ) {
    517                                         //      auto callExpr = new ast::UntypedExpr(
    518                                         //              expr->location, new ast::NameExpr( expr->location, "valueE"), {expr} );
    519                                         //      CandidateFinder finder( context, env );
    520                                         //      finder.find( callExpr );
    521                                         //      CandidateList winners = findMinCost( finder.candidates );
    522                                         //      if (winners.size() != 1) {
    523                                         //              SemanticError( callExpr, "Ambiguous expression in valueE" );
    524                                         //      }
    525                                         //      CandidateRef & choice = winners.front();
    526                                         //      choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    527 
    528                                         //      results.emplace_back(
    529                                         //              i, choice->expr,
    530                                         //              std::move( env ), std::move( need ), std::move( have ), std::move( open ),
    531                                         //              nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    532                                         // } else {
    533                                                 results.emplace_back(
    534                                                         i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ),
    535                                                         nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    536                                         //}
     513                                        results.emplace_back(
     514                                                i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ),
     515                                                nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    537516                                }
    538517                        }
     
    806785                                        auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>();
    807786                                        if ( !instantiateArgument( location,
    808                                                 funcType->params[i], obj->init, args, results, genStart, context)) return;
     787                                                funcType->params[i], obj->init, args, results, genStart, symtab)) return;
    809788                                }
    810789                                goto endMatch;
     
    816795                        // no default args for indirect calls
    817796                        if ( !instantiateArgument( location,
    818                                 param, nullptr, args, results, genStart, context ) ) return;
     797                                param, nullptr, args, results, genStart, symtab ) ) return;
    819798                }
    820799
     
    911890                } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) {
    912891                        addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" );
    913                 } else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) {
    914                         if ( enumInst->base->base ) {
    915                                 CandidateFinder finder( context, tenv );
    916                                 auto location = aggrExpr->location;
    917                                 auto callExpr = new ast::UntypedExpr(
    918                                         location, new ast::NameExpr( location, "valueE" ), {aggrExpr}
    919                                 );
    920                                 finder.find( callExpr );
    921                                 CandidateList winners = findMinCost( finder.candidates );
    922                                 if (winners.size() != 1) {
    923                                         SemanticError( callExpr, "Ambiguous expression in valueE" );
    924                                 }
    925                                 CandidateRef & choice = winners.front();
    926                                 // choice->cost.incSafe();
    927                                 candidates.emplace_back( std::move(choice) );
    928                         }
    929 
     892                }
     893                else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) {
     894                        if (enumInst->base && enumInst->base->base) {
     895            const CodeLocation &location = cand->expr->location;
     896
     897            CandidateFinder funcFinder(context, tenv);
     898            auto nameExpr = new ast::NameExpr(location, "valueE");
     899            ResolveMode mode = {true, false, selfFinder.candidates.empty()};
     900            funcFinder.find( nameExpr, mode );
     901
     902            // make variableExpr itself the candidate for the value Call
     903            ExplodedArgs argExpansions;
     904            argExpansions.emplace_back();
     905            auto &argE = argExpansions.back();
     906
     907            argE.emplace_back(*cand, symtab); // Use the typed name expr as param for value
     908
     909            CandidateList found;
     910            SemanticErrorException errors;
     911
     912            for (CandidateRef &func : funcFinder) {
     913                try {
     914                    const ast::Type *funcResult =
     915                        func->expr->result->stripReferences();
     916                    if (auto pointer = dynamic_cast<const ast::PointerType *>(
     917                            funcResult)) {
     918                        if (auto function =
     919                                pointer->base.as<ast::FunctionType>()) {
     920                            CandidateRef newFunc{new Candidate{*func}};
     921                            newFunc->expr = referenceToRvalueConversion(
     922                                newFunc->expr, newFunc->cost);
     923                            makeFunctionCandidates( location,
     924                                                   newFunc, function,
     925                                                   argExpansions, found );
     926                        }
     927                    }
     928                } catch (SemanticErrorException &e) {
     929                    std::cerr
     930                        << "Resolving value function should cause an error"
     931                        << std::endl;
     932                    errors.append(e);
     933                }
     934            }
     935
     936            if (found.empty()) {
     937                std::cerr << "Resolve value function should always success"
     938                          << std::endl;
     939            }
     940
     941            for (CandidateRef &withFunc : found) {
     942                withFunc->cost.incSafe();
     943                Cost cvtCost =
     944                    computeApplicationConversionCost(withFunc, symtab);
     945                assert(cvtCost != Cost::infinity);
     946
     947                candidates.emplace_back(std::move(withFunc));
     948            }
     949        }
    930950                }
    931951        }
     
    13941414                        ast::Expr * newExpr = data.combine( nameExpr->location, cost );
    13951415
    1396                         bool bentConversion = false;
    1397                         if ( auto inst = newExpr->result.as<ast::EnumInstType>() ) {
    1398                                 if ( inst->base && inst->base->base ) {
    1399                                         bentConversion = true;
    1400                                 }
    1401                         }
    1402                        
    14031416                        CandidateRef newCand = std::make_shared<Candidate>(
    1404                                 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, bentConversion? Cost::safe: Cost::zero,
     1417                                newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
    14051418                                cost );
    14061419
     
    14351448        auto cand = new Candidate(variableExpr, tenv);
    14361449        candidates.emplace_back(cand);
     1450
     1451        if (auto enumInst = dynamic_cast<const ast::EnumInstType *>(
     1452                variableExpr->var->get_type())) {
     1453            if (enumInst->base && enumInst->base->base) {
     1454                const CodeLocation &location = cand->expr->location;
     1455
     1456                CandidateFinder funcFinder(context, tenv);
     1457                auto nameExpr = new ast::NameExpr(location, "valueE");
     1458                ResolveMode mode = {true, false, selfFinder.candidates.empty()};
     1459                funcFinder.find( nameExpr, mode );
     1460
     1461                // make variableExpr itself the candidate for the value Call
     1462                ExplodedArgs argExpansions;
     1463                argExpansions.emplace_back();
     1464                auto &argE = argExpansions.back();
     1465
     1466                argE.emplace_back(*cand, symtab);
     1467
     1468                CandidateList found;
     1469                SemanticErrorException errors;
     1470
     1471                for (CandidateRef &func : funcFinder) {
     1472                    try {
     1473                    const ast::Type *funcResult =
     1474                        func->expr->result->stripReferences();
     1475                    if (auto pointer = dynamic_cast<const ast::PointerType *>(
     1476                            funcResult)) {
     1477                        if (auto function =
     1478                                pointer->base.as<ast::FunctionType>()) {
     1479                            CandidateRef newFunc{new Candidate{*func}};
     1480                            newFunc->expr = referenceToRvalueConversion(
     1481                                newFunc->expr, newFunc->cost);
     1482                            makeFunctionCandidates(variableExpr->location,
     1483                                                   newFunc, function,
     1484                                                   argExpansions, found);
     1485                        }
     1486                    }
     1487                    } catch (SemanticErrorException &e) {
     1488                        std::cerr
     1489                            << "Resolving value function should cause an error"
     1490                            << std::endl;
     1491                        errors.append(e);
     1492                    }
     1493                }
     1494
     1495                if (found.empty()) {
     1496                    std::cerr << "Resolve value function should always success"
     1497                            << std::endl;
     1498                }
     1499
     1500                for (CandidateRef &withFunc : found) {
     1501                    withFunc->cost.incSafe();
     1502                    Cost cvtCost =
     1503                        computeApplicationConversionCost(withFunc, symtab);
     1504                    assert(cvtCost != Cost::infinity);
     1505
     1506                    candidates.emplace_back(std::move(withFunc));
     1507                }
     1508            }
     1509        }
    14371510    }
    14381511
     
    17661839
    17671840                                // unification run for side-effects
    1768                                 ast::ptr<ast::Type> common;
    1769                                 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, common );
     1841                                bool canUnify = unify( toType, cand->expr->result, env, need, have, open );
    17701842                                (void) canUnify;
    17711843                                Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     
    17921864                                        // ambiguous case, still output candidates to print in error message
    17931865                                        if ( cand->cost == minExprCost && thisCost == minCastCost ) {
    1794                                                 auto commonAsEnumAttr = common.as<ast::EnumAttrType>();
    1795                                                 if ( commonAsEnumAttr && commonAsEnumAttr->attr == ast::EnumAttribute::Value ) {
    1796                                                        
    1797                                                         auto callExpr = new ast::UntypedExpr(
    1798                                                                 cand->expr->location, new ast::NameExpr( cand->expr->location, "valueE"), {cand->expr} );
    1799                                                         CandidateFinder finder( context, env );
    1800                                                         finder.find( callExpr );
    1801                                                         CandidateList winners = findMinCost( finder.candidates );
    1802                                                         if (winners.size() != 1) {
    1803                                                                 SemanticError( callExpr, "Ambiguous expression in valueE" );
    1804                                                         }
    1805                                                         CandidateRef & choice = winners.front();
    1806                                                         // assert( valueCall->result );
    1807                                                         CandidateRef newCand = std::make_shared<Candidate>(
    1808                                                                 new ast::InitExpr{
    1809                                                                         initExpr->location,
    1810                                                                         // restructureCast( cand->expr, toType ),
    1811                                                                         choice->expr,
    1812                                                                         initAlt.designation },
    1813                                                                 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost );
    1814                                                                 inferParameters( newCand, matches );
    1815                                                 } else {
    1816                                                         CandidateRef newCand = std::make_shared<Candidate>(
    1817                                                                 new ast::InitExpr{
    1818                                                                         initExpr->location,
    1819                                                                         restructureCast( cand->expr, toType ),
    1820                                                                         initAlt.designation },
    1821                                                                 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost );
    1822                                                         // currently assertions are always resolved immediately so this should have no effect.
    1823                                                         // if this somehow changes in the future (e.g. delayed by indeterminate return type)
    1824                                                         // we may need to revisit the logic.
    1825                                                         inferParameters( newCand, matches );   
    1826                                                 }
    1827                                         }                       
    1828                                 }       
     1866                                                CandidateRef newCand = std::make_shared<Candidate>(
     1867                                                        new ast::InitExpr{
     1868                                                                initExpr->location,
     1869                                                                restructureCast( cand->expr, toType ),
     1870                                                                initAlt.designation },
     1871                                                        std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost );
     1872                                                // currently assertions are always resolved immediately so this should have no effect.
     1873                                                // if this somehow changes in the future (e.g. delayed by indeterminate return type)
     1874                                                // we may need to revisit the logic.
     1875                                                inferParameters( newCand, matches );
     1876                                        }
     1877                                }
    18291878                        }
    18301879                }
     
    18511900                                                std::make_shared<Candidate>(
    18521901                                                        newExpr, copy( tenv ), ast::OpenVarSet{},
    1853                                                         ast::AssertionSet{}, Cost::safe, cost
     1902                                                        ast::AssertionSet{}, Cost::zero, cost
    18541903                                                );
    18551904
     
    21512200}
    21522201
    2153 // get the valueE(...) ApplicationExpr that returns the enum value
    2154 const ast::Expr * getValueEnumCall(
    2155         const ast::Expr * expr,
    2156         const ResolvExpr::ResolveContext & context, const ast::TypeEnvironment & env ) {
    2157                 auto callExpr = new ast::UntypedExpr(
    2158                         expr->location, new ast::NameExpr( expr->location, "valueE"), {expr} );
    2159                 CandidateFinder finder( context, env );
    2160                 finder.find( callExpr );
    2161                 CandidateList winners = findMinCost( finder.candidates );
    2162                 if (winners.size() != 1) {
    2163                         SemanticError( callExpr, "Ambiguous expression in valueE" );
    2164                 }
    2165                 CandidateRef & choice = winners.front();
    2166                 return choice->expr;
    2167 }
    2168 
    21692202const ast::Expr * createCondExpr( const ast::Expr * expr ) {
    21702203        assert( expr );
  • src/ResolvExpr/CandidateFinder.hpp

    rdc58e5d r7a36848  
    7070        const ast::Expr * expr, Cost & cost );
    7171
    72 const ast::Expr * getValueEnumCall(const ast::Expr * expr,
    73         const ResolvExpr::ResolveContext & context, const ast::TypeEnvironment & env );
    7472/// Wrap an expression to convert the result to a conditional result.
    7573const ast::Expr * createCondExpr( const ast::Expr * expr );
  • src/ResolvExpr/CommonType.cc

    rdc58e5d r7a36848  
    385385                } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) {
    386386                        const ast::EnumDecl* enumDecl = enumInst->base;
    387                         if ( !enumDecl->base ) {
     387                        if ( enumDecl->base ) {
     388                                result = enumDecl->base.get();
     389                        } else {
    388390                                ast::BasicType::Kind kind = commonTypes[ basic->kind ][ ast::BasicType::SignedInt ];
    389391                                if (
     
    396398                                }
    397399                        }
    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             }
     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                        }
    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;
    428441        }
    429442
     
    594607                        result = pointer;
    595608                        add_qualifiers( result, type2->qualifiers );
    596                 }
    597         }
    598 
    599         void postvisit( const ast::ArrayType * arr ) {}
     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        }
    600618
    601619        void postvisit( const ast::ReferenceType * ref ) {
     
    641659        }
    642660
    643         void postvisit( const ast::FunctionType * func) {}
    644 
    645         void postvisit( const ast::StructInstType * inst ) {}
    646 
    647         void postvisit( const ast::UnionInstType * inst ) {}
     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        }
    648672
    649673        void postvisit( const ast::EnumInstType * enumInst ) {
    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 * ) {}
     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        }
    657693
    658694        void postvisit( const ast::TraitInstType * ) {}
     
    660696        void postvisit( const ast::TypeInstType * ) {}
    661697
    662         void postvisit( const ast::TupleType * tuple ) {}
     698        void postvisit( const ast::TupleType * tuple ) {
     699                tryResolveWithTypedEnum( tuple );
     700        }
    663701
    664702        void postvisit( const ast::VarArgsType * ) {}
     
    677715                } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) {
    678716                        const ast::EnumDecl * enumDecl = enumInst->base;
    679                         if ( !enumDecl->base ) {
     717                        if ( enumDecl->base ) {
     718                                if ( tryResolveWithTypedEnum( zero ) )
     719                                        add_qualifiers( result, zero->qualifiers );
     720                        } else {
    680721                                if ( widen.second || zero->qualifiers <= type2->qualifiers ) {
    681722                                        result = type2;
     
    697738                                ast::BasicType::SignedInt, one->qualifiers | type2->qualifiers };
    698739                } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) {
    699                         const ast::EnumDecl * enumDecl = enumInst->base;
    700                         if ( !enumDecl->base ) {
     740                        const ast::EnumDecl * enumBase = enumInst->base;
     741                        if ( enumBase->base ) {
     742                                if ( tryResolveWithTypedEnum( one ))
     743                                        add_qualifiers( result, one->qualifiers );
     744                        } else {
    701745                                if ( widen.second || one->qualifiers <= type2->qualifiers ) {
    702746                                        result = type2;
  • src/ResolvExpr/ConversionCost.cc

    rdc58e5d r7a36848  
    278278        if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
    279279                conversionCostFromBasicToBasic( basicType, dstAsBasic );
    280         } else if ( dynamic_cast< const ast::EnumAttrType *>(dst) ) {
     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) ) {
    281291                static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
    282292                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                 }
    288293        }
    289294}
     
    361366}
    362367
    363 void 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         }
     368void ConversionCost::postvisit( const ast::EnumInstType * ) {
    386369        static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
    387370        cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
     
    391374}
    392375
    393 void 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     }
     376void 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
    422392}
    423393
     
    496466                cost.incSafe( maxIntCost + 2 );
    497467                // 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                 }
    503468        }
    504469}
     
    518483                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    519484                }
    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                 }
    525485        }
    526486}
  • src/ResolvExpr/ConversionCost.h

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

    rdc58e5d r7a36848  
    274274                void previsit( const ast::Node * ) { visit_children = false; }
    275275
    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                         ;
     276                void postvisit( const ast::VoidType * ) {
     277                        result = dynamic_cast< const ast::VoidType * >( type2 );
    280278                }
    281279
     
    284282                                result = basic->kind == basic2->kind;
    285283                        }
    286                         result = result || tryToUnifyWithEnumValue(basic, type2, tenv, need, have, open, noWiden());
    287284                }
    288285
     
    293290                                        noWiden());
    294291                        }
    295                         result = result || tryToUnifyWithEnumValue(pointer, type2, tenv, need, have, open, noWiden());
    296292                }
    297293
     
    311307
    312308                        result = unifyExact(
    313                                 array->base, array2->base, tenv, need, have, open, noWiden())
    314                                 || tryToUnifyWithEnumValue(array, type2, tenv, need, have, open, noWiden());
     309                                array->base, array2->base, tenv, need, have, open, noWiden());
    315310                }
    316311
     
    404399                }
    405400
    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 
    420401        public:
    421402                void postvisit( const ast::FunctionType * func ) {
     
    526507                void postvisit( const ast::StructInstType * aggrType ) {
    527508                        handleGenericRefType( aggrType, type2 );
    528                         result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
    529509                }
    530510
    531511                void postvisit( const ast::UnionInstType * aggrType ) {
    532512                        handleGenericRefType( aggrType, type2 );
    533                         result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
    534513                }
    535514
    536515                void postvisit( const ast::EnumInstType * aggrType ) {
    537516                        handleRefType( aggrType, type2 );
    538                         result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
    539                 }
    540 
    541                 void postvisit( const ast::EnumAttrType * enumAttr ) {
     517                }
     518
     519                void postvisit( const ast::EnumPosType * posType ) {
    542520                        // Lazy approach for now
    543                         if ( auto otherPos = dynamic_cast< const ast::EnumAttrType *>(type2) ) {
    544                             if ( enumAttr->match(otherPos) ) {
    545                                     result = otherPos;
    546                             }
    547             } 
     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                        }
    548526                }
    549527
    550528                void postvisit( const ast::TraitInstType * aggrType ) {
    551529                        handleRefType( aggrType, type2 );
    552                         result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());
    553530                }
    554531
     
    559536                                this->result = otherInst;
    560537                        }
    561                         result = result || tryToUnifyWithEnumValue(typeInst, type2, tenv, need, have, open, noWiden());
    562538                }
    563539
     
    634610                        auto types2 = flatten( flat2 );
    635611
    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());
     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 );
    653625                }
    654626        };
  • src/SymTab/Mangler.cc

    rdc58e5d r7a36848  
    5858        void postvisit( const ast::OneType * oneType );
    5959        void postvisit( const ast::QualifiedType * qualType );
    60         void postvisit( const ast::EnumAttrType * posType );
     60
     61        void postvisit( const ast::EnumPosType * posType );
    6162
    6263        /// The result is the current constructed mangled name.
     
    280281}
    281282
    282 void 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 
     283void Mangler::postvisit( const ast::EnumPosType * pos ) {
     284        postvisit( pos->instance );
     285        mangleName += "_pos";
    298286}
    299287
  • src/Validate/Autogen.cpp

    rdc58e5d r7a36848  
    196196
    197197        bool shouldAutogen() const final { return true; }
     198        void genAttrFuncForward();
     199        void genPosFunctions();
    198200private:
    199201        void genFuncBody( ast::FunctionDecl * decl ) final;
    200202        void genFieldCtors() final;
    201203        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();
    202216};
    203217
     
    242256        enumInst.base = enumDecl;
    243257        EnumFuncGenerator gen( enumDecl, &enumInst, functionNesting );
     258        if ( enumDecl->base ) {
     259                gen.genAttrFuncForward();
     260                gen.genPosFunctions();
     261        }
    244262        gen.generateAndAppendFunctions( declsToAddAfter );
    245263}
     
    400418}
    401419
    402 /// Use the current type T to create `void ^?{}(T & _dst)`.
     420/// Use the current type T to create `void ?{}(T & _dst)`.
    403421ast::FunctionDecl * FuncGenerator::genDtorProto() const {
    404422        // The destructor must be mutex on a concurrent type.
     
    759777}
    760778
     779ast::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
     787ast::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
     795ast::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
     801ast::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
     807ast::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
     813ast::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
     823ast::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
     833ast::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
     881void 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
     896void 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
    761906void TypeFuncGenerator::genFieldCtors() {
    762907        // Opaque types do not have field constructors.
  • src/Validate/ReplacePseudoFunc.cpp

    rdc58e5d r7a36848  
    1717namespace {
    1818
     19std::set<std::string> queryLabels;
     20std::set<std::string> queryValues;
     21
     22struct 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
     33const 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
     41struct 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
     52struct FindGenEnumArray final : public ast::WithShortCircuiting {
     53    void previsit(const ast::ApplicationExpr* enumDecl);
     54};
     55
     56struct 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
     63struct 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
     78void 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
     91void WrapEnumValueExpr::previsit(const ast::DeclStmt*) {
     92    visit_children = false;
     93}
     94
     95void WrapEnumValueExpr::previsit(const ast::CastExpr* expr) {
     96    if (expr->result && expr->result.as<ast::ReferenceType>()) {
     97        visit_children = false;
     98    }
     99}
     100
     101ast::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
     120void 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
     147const 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
     170void 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
     228ast::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
     264ast::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}
     338
    19339ast::ptr<ast::Expr> reduceCastExpr(ast::ptr<ast::Expr> expr) {
    20340    if (auto castExpr = expr.as<ast::CastExpr>()) {
     
    37357                    if (auto enumInst =
    38358                            argAsDecl->type.as<ast::EnumInstType>()) {
    39                         auto castTo = new ast::EnumAttrType(
    40                             enumInst, ast::EnumAttribute::Posn);
     359                        auto castTo = new ast::EnumPosType(enumInst);
    41360                        auto castExpr =
    42361                            new ast::CastExpr(param->location, param, castTo);
     
    56375                        return ast::deepCopy(ret);
    57376                    } else if (auto posType =
    58                                    argAsDecl->type.as<ast::EnumAttrType>()) {
    59                         std::cerr << "PseudoFunc: succ/pred should not be applied on EnumAttrType directly" << std::endl;
     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);
    60415                    }
    61416                }
     
    69424
    70425void 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
    71432    ast::Pass<ReplaceSuccAndPred>::run(translationUnit);
    72433}
  • src/Validate/module.mk

    rdc58e5d r7a36848  
    5454        Validate/VerifyCtorDtorAssign.hpp \
    5555        Validate/ReplacePseudoFunc.cpp \
    56         Validate/ReplacePseudoFunc.hpp \
    57         Validate/ImplementEnumFunc.cpp \
    58         Validate/ImplementEnumFunc.hpp
     56        Validate/ReplacePseudoFunc.hpp
    5957
    6058SRCDEMANGLE += $(SRC_VALIDATE)
  • src/main.cc

    rdc58e5d r7a36848  
    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() ); // Here
     385                PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() );
    386386                PASS( "Erase With", ResolvExpr::eraseWith, transUnit );
    387387
Note: See TracChangeset for help on using the changeset viewer.