Changeset 3f9a8d0


Ignore:
Timestamp:
Feb 26, 2024, 8:17:20 AM (7 weeks ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
master
Children:
f1149ac
Parents:
1bb76ad (diff), a4da45e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
1 added
17 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Fwd.hpp

    r1bb76ad r3f9a8d0  
    133133class OneType;
    134134class GlobalScopeType;
     135class EnumPosType;
    135136
    136137class Designation;
  • src/AST/Pass.hpp

    r1bb76ad r3f9a8d0  
    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;
    224225        const ast::Type *             visit( const ast::TraitInstType        * ) override final;
    225226        const ast::Type *             visit( const ast::TypeInstType         * ) override final;
  • src/AST/Pass.impl.hpp

    r1bb76ad r3f9a8d0  
    19861986
    19871987//--------------------------------------------------------------------------
     1988// EnumPosType
     1989template< typename core_t >
     1990const ast::Type * ast::Pass< core_t >::visit( const ast::EnumPosType * node ) {
     1991        VISIT_START( node );
     1992
     1993        VISIT_END( Type, node );
     1994}
     1995
     1996//--------------------------------------------------------------------------
    19881997// TraitInstType
    19891998template< typename core_t >
  • src/AST/Print.cpp

    r1bb76ad r3f9a8d0  
    15761576        }
    15771577
     1578        virtual const ast::Type * visit( const ast::EnumPosType * node ) override final {
     1579                preprint( node );
     1580                os << "enum pos with ";
     1581                (*(node->instance)).accept( *this );
     1582                return node;
     1583        }
     1584
    15781585        virtual const ast::Type * visit( const ast::TraitInstType * node ) override final {
    15791586                preprint( node );
  • src/AST/Type.hpp

    r1bb76ad r3f9a8d0  
    362362using EnumInstType = SueInstType<EnumDecl>;
    363363
     364class EnumPosType final : public Type {
     365public:
     366        readonly<EnumInstType> instance;
     367        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     368        EnumPosType( const EnumInstType * instance ): instance(instance) {}
     369       
     370private:
     371        EnumPosType * clone() const override { return new EnumPosType{ *this }; }
     372        MUTATE_FRIEND
     373};
     374
    364375/// An instance of a trait type.
    365376class TraitInstType final : public BaseInstType {
  • src/AST/Visitor.hpp

    r1bb76ad r3f9a8d0  
    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;
    121122    virtual const ast::Designation *      visit( const ast::Designation          * ) = 0;
    122123    virtual const ast::Init *             visit( const ast::SingleInit           * ) = 0;
  • src/CodeGen/GenType.cc

    r1bb76ad r3f9a8d0  
    4646        void postvisit( ast::UnionInstType const * type );
    4747        void postvisit( ast::EnumInstType const * type );
     48        void postvisit( ast::EnumPosType const * type );
    4849        void postvisit( ast::TypeInstType const * type );
    4950        void postvisit( ast::TupleType const * type );
     
    239240}
    240241
     242void GenType::postvisit( ast::EnumPosType const * type ) {
     243        postvisit( type->instance );
     244}
     245
    241246void GenType::postvisit( ast::TypeInstType const * type ) {
    242247        assertf( !options.genC, "TypeInstType should not reach code generation." );
  • src/Common/CodeLocationTools.cpp

    r1bb76ad r3f9a8d0  
    188188    macro(UnionInstType, Type) \
    189189    macro(EnumInstType, Type) \
     190    macro(EnumPosType, Type) \
    190191    macro(TraitInstType, Type) \
    191192    macro(TypeInstType, Type) \
  • src/Parser/parser.yy

    r1bb76ad r3f9a8d0  
    30223022        | assertion_list
    30233023                { $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); }
     3024        | ENUM '(' identifier_or_type_name ')' identifier_or_type_name new_type_class type_initializer_opt assertion_list_opt
     3025                {       
     3026                        typedefTable.addToScope( *$3, TYPEDIMname, "type_parameter 4" );
     3027                        typedefTable.addToScope( *$5, TYPEDIMname, "type_parameter 5" );
     3028                        $$ = DeclarationNode::newTypeParam( $6, $5 )->addTypeInitializer( $7 )->addAssertions( $8 );
     3029                }
    30243030        ;
    30253031
  • src/ResolvExpr/CandidateFinder.cpp

    r1bb76ad r3f9a8d0  
    891891                } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) {
    892892                        addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" );
    893                 } else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) {
    894                         // The Attribute Arrays are not yet generated, need to proxy them
    895                         // as attribute function call
    896                         const CodeLocation & location = cand->expr->location;
    897                         if ( enumInst->base && enumInst->base->base ) {
    898                                 auto valueName = new ast::NameExpr(location, "valueE");
    899                                 auto untypedValueCall = new ast::UntypedExpr(
    900                                         location, valueName, { aggrExpr } );
    901                                 auto result = ResolvExpr::findVoidExpression( untypedValueCall, context );
    902                                 assert( result.get() );
    903                                 CandidateRef newCand = std::make_shared<Candidate>(
    904                                         *cand, result, Cost::safe );
    905                                 candidates.emplace_back( std::move( newCand ) );
    906                         }
     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        }
    907951                }
    908952        }
     
    14001444        }
    14011445
    1402         void Finder::postvisit( const ast::VariableExpr * variableExpr ) {
    1403                 // not sufficient to just pass `variableExpr` here, type might have changed since
    1404                 addCandidate( variableExpr, tenv );
    1405         }
     1446    void Finder::postvisit(const ast::VariableExpr *variableExpr) {
     1447        // not sufficient to just pass `variableExpr` here, type might have changed
     1448
     1449        auto cand = new Candidate(variableExpr, tenv);
     1450        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        }
     1511    }
    14061512
    14071513        void Finder::postvisit( const ast::ConstantExpr * constantExpr ) {
  • src/ResolvExpr/CommonType.cc

    r1bb76ad r3f9a8d0  
    397397                                        result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers };
    398398                                }
     399                        }
     400                } else if ( const ast::EnumPosType * pos = 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 };
    399409                        }
    400410                }
  • src/ResolvExpr/ConversionCost.cc

    r1bb76ad r3f9a8d0  
    278278        if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
    279279                conversionCostFromBasicToBasic( basicType, dstAsBasic );
    280         } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
     280        }
     281        else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
    281282                auto enumDecl = enumInst->base;
    282                 if ( auto baseType = enumDecl->base.get() ) {
    283                         cost = costCalc( basicType, baseType, srcIsLvalue, symtab, env );
    284                         cost.incUnsafe();
     283                if ( enumDecl->base.get() ) {
     284                        // cost = costCalc( basicType, baseType, srcIsLvalue, symtab, env );
     285                        // cost.incUnsafe();
     286                        cost = Cost::infinity;
    285287                } else {
    286288            cost = Cost::unsafe;
     
    365367        cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
    366368        // }
     369        if ( cost < Cost::unsafe ) {
     370                cost.incSafe();
     371        }
     372}
     373
     374void ConversionCost::postvisit( const ast::EnumPosType * ) {
     375        static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
     376        cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
    367377        if ( cost < Cost::unsafe ) {
    368378                cost.incSafe();
  • src/ResolvExpr/ConversionCost.h

    r1bb76ad r3f9a8d0  
    7272        void postvisit( const ast::ZeroType * zeroType );
    7373        void postvisit( const ast::OneType * oneType );
     74        void postvisit( const ast::EnumPosType * posType );
    7475private:
    7576        // refactor for code resue
  • src/ResolvExpr/Unify.cc

    r1bb76ad r3f9a8d0  
    517517                }
    518518
     519                void postvisit( const ast::EnumPosType * posType ) {
     520                        // Does nothing for now. Handled in ReplacePseudoFunc
     521                        // Might move here in the future
     522                }
     523
    519524                void postvisit( const ast::TraitInstType * aggrType ) {
    520525                        handleRefType( aggrType, type2 );
  • src/SymTab/Mangler.cc

    r1bb76ad r3f9a8d0  
    5959        void postvisit( const ast::QualifiedType * qualType );
    6060
     61        void postvisit( const ast::EnumPosType * posType );
     62
    6163        /// The result is the current constructed mangled name.
    6264        std::string result() const { return mangleName; }
     
    277279        assertf( decl->kind < ast::TypeDecl::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
    278280        mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name;
     281}
     282
     283void Mangler::postvisit( const ast::EnumPosType * pos ) {
     284        postvisit( pos->instance );
     285        mangleName += "_pos";
    279286}
    280287
  • src/Validate/Autogen.cpp

    r1bb76ad r3f9a8d0  
    205205        ast::FunctionDecl * genLabelProto() const;
    206206        ast::FunctionDecl * genValueProto() const;
     207        // ast::FunctionDecl * genValueProto2() const;
    207208};
    208209
     
    789790}
    790791
     792// ast::FunctionDecl * EnumFuncGenerator::genValueProto2() const {
     793//      return genProto( "valueE",
     794//              { new ast::ObjectDecl( getLocation(), "_i", new ast::EnumPosType( new ast::EnumInstType( decl ) ) )},
     795//              { new ast::ObjectDecl( getLocation(), "_ret", ast::deepCopy( decl->base ) ) } );
     796// }
     797
    791798void EnumFuncGenerator::genAttrFuncForward() { 
    792799        if ( decl->base ) {
    793800                ast::FunctionDecl *(EnumFuncGenerator::*attrProtos[3])() const = {
    794801                        &EnumFuncGenerator::genPosProto, &EnumFuncGenerator::genLabelProto,
    795                         &EnumFuncGenerator::genValueProto };
     802                        &EnumFuncGenerator::genValueProto
     803                        // , &EnumFuncGenerator::genValueProto2
     804                        };
    796805                for ( auto & generator : attrProtos ) {
    797806                        produceForwardDecl( (this->*generator)() );
  • src/Validate/ReplacePseudoFunc.cpp

    r1bb76ad r3f9a8d0  
    66#include "AST/Inspect.hpp"
    77#include "AST/Pass.hpp"
     8#include "AST/Print.hpp"
    89#include "AST/Stmt.hpp"
    910#include "Common/utility.h"
     11#include "ResolvExpr/CandidateFinder.hpp"
    1012#include "ResolvExpr/Resolver.h"
    1113#include "SymTab/Mangler.h"
    1214
    13 #include "AST/Print.hpp"
    14 
    15 #include "ResolvExpr/CandidateFinder.hpp"
    16 
    1715namespace Validate {
    1816
     
    2119std::set<std::string> queryLabels;
    2220std::set<std::string> queryValues;
     21
     22struct ReplaceEnumInstWithPos final : public ast::WithShortCircuiting {
     23    void previsit(const ast::ObjectDecl*) { visit_children = false; }
     24    const ast::ObjectDecl* postvisit(const ast::ObjectDecl* decl) {
     25        auto enumInst = decl->type.strict_as<ast::EnumInstType>();
     26        auto enumPos = new ast::EnumPosType(enumInst);
     27        auto ret = ast::mutate_field(decl, &ast::ObjectDecl::type, enumPos);
     28        ret = ast::mutate_field(ret, &ast::ObjectDecl::mangleName,
     29                                Mangle::mangle(ret));
     30        return ret;
     31    }
     32};
     33
     34const inline std::string getValueArrayName(std::string enumName) {
     35    return "values_" + enumName;
     36}
    2337
    2438// struct AutoInit {
     
    3246    void previsit(const ast::ApplicationExpr* expr);
    3347    void previsit(const ast::CastExpr* expr);
    34     void previsit(const ast::VariableExpr* ) { visit_children = false; }
     48    void previsit(const ast::VariableExpr*) { visit_children = false; }
    3549
    3650    ast::Expr const* postvisit(const ast::VariableExpr* expr);
     
    6680    auto varExpr = expr->func.as<ast::VariableExpr>();
    6781    auto fname = ast::getFunctionName(expr);
    68         if ( !varExpr || varExpr->var->linkage == ast::Linkage::Intrinsic ) {
    69         if ( fname == "?{}" || fname == "?=?" )
    70                     visit_children = false;
    71         }
     82    if (!varExpr || varExpr->var->linkage == ast::Linkage::Intrinsic) {
     83        if (fname == "?{}" || fname == "?=?") visit_children = false;
     84    }
    7285
    7386    if (fname == "labelE" || fname == "valueE" || fname == "posE") {
     
    94107            auto untyped = new ast::UntypedExpr(
    95108                expr->location, new ast::NameExpr(expr->location, "valueE"),
    96                 { std::move( expr ) });
     109                {std::move(expr)});
    97110            ResolvExpr::ResolveContext context{symtab, transUnit().global};
    98111            auto result = ResolvExpr::findVoidExpression(untyped, context);
    99112            ast::ptr<ast::ApplicationExpr> ret =
    100                     result.strict_as<ast::ApplicationExpr>();
    101             return ast::deepCopy( ret );
     113                result.strict_as<ast::ApplicationExpr>();
     114            return ast::deepCopy(ret);
    102115        }
    103116    }
     
    132145}
    133146
    134 const ast::Init * getAutoInit( const CodeLocation & location,
    135     const ast::Type * type, ResolvExpr::ResolveContext context, const ast::Init * prev ) {
    136     if ( auto prevInit = dynamic_cast< const ast::SingleInit * >( prev ) ) {
     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)) {
    137152        auto prevInitExpr = prevInit->value;
    138         if ( auto constInit = prevInitExpr.as< ast::ConstantExpr >() ) {
     153        if (auto constInit = prevInitExpr.as<ast::ConstantExpr>()) {
    139154            // Assume no string literal for now
    140155            return new ast::SingleInit(
    141                 location,
    142                 ast::ConstantExpr::from_int(
    143                     location, constInit->intValue() + 1 )
    144             );
     156                location, ast::ConstantExpr::from_int(
     157                              location, constInit->intValue() + 1));
    145158        } else {
    146159            auto untypedThisInit = new ast::UntypedExpr(
    147                     location,
    148                     new ast::NameExpr( location, "?++" ),
    149                     { prevInitExpr }
    150                 );
    151             auto typedInit = ResolvExpr::findSingleExpression(untypedThisInit, type,
    152                 context );
    153             return new ast::SingleInit( location, typedInit );
    154         }
    155     }
    156     SemanticError( prev, "Auto Init a List is not implemented" );
     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");
    157167    return prev;
    158168}
     
    167177    auto type = enumDecl->base;
    168178
    169     for ( size_t i = 0; i < enumDecl->members.size(); i++ ) {
    170         ast::ptr<ast::Decl> mem = enumDecl->members.at( i );
    171         auto memAsObjectDecl = mem.as< ast::ObjectDecl >();
    172         assert( memAsObjectDecl );
    173         if ( memAsObjectDecl->init ) {
    174             inits.emplace_back( memAsObjectDecl->init );
     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);
    175185        } else {
    176             const CodeLocation & location = mem->location;
    177             if ( i == 0 ) {
    178                 inits.emplace_back( new ast::SingleInit(
    179                     location,
    180                     ast::ConstantExpr::from_int( mem->location, 0 )
    181                 ) );
     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)));
    182190            } else {
    183                 inits.emplace_back( getAutoInit( location, enumDecl->base,
    184                     ResolvExpr::ResolveContext{symtab, transUnit().global},
    185                     inits.at( i - 1 ).as<ast::SingleInit>()) );
     191                inits.emplace_back(getAutoInit(
     192                    location, enumDecl->base,
     193                    ResolvExpr::ResolveContext{symtab, transUnit().global},
     194                    inits.at(i - 1).as<ast::SingleInit>()));
    186195            }
    187196        }
    188197        labels.emplace_back(new ast::SingleInit(
    189         location, ast::ConstantExpr::from_string(location, mem->name)));
    190     } 
     198            location, ast::ConstantExpr::from_string(location, mem->name)));
     199    }
    191200    if (queryValues.count(enumDecl->name)) {
    192201        auto init = new ast::ListInit(location, std::move(inits));
     
    219228ast::ApplicationExpr const* getPseudoFuncApplication(
    220229    const CodeLocation location, ResolvExpr::ResolveContext context,
    221     const ast::VariableExpr* arg, const ast::EnumDecl* base, const std::string & name) {
     230    const ast::VariableExpr* arg, const ast::EnumDecl* base,
     231    const std::string& name) {
    222232    ast::Expr* toResolve = new ast::NameExpr(location, name + base->name);
    223     auto result = ResolvExpr::findVoidExpression(toResolve, context);
    224     assert(result.get());
    225     auto arrAsVar = result.strict_as<ast::VariableExpr>();
    226     auto untyped = new ast::UntypedExpr(
    227         location, new ast::NameExpr(location, "?[?]"),
    228         { std::move(arrAsVar), std::move(arg) });
    229     auto typedResult = ResolvExpr::findVoidExpression(untyped, context);
    230 
    231     ast::ptr<ast::ApplicationExpr> ret =
    232         typedResult.strict_as<ast::ApplicationExpr>();
    233     return ast::deepCopy(ret);
     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        auto untyped =
     244            new ast::UntypedExpr(location, new ast::NameExpr(location, "?[?]"),
     245                                 {std::move(arrAsVar), mutatedArg});
     246        auto typedResult = ResolvExpr::findVoidExpression(untyped, context);
     247        ast::ptr<ast::ApplicationExpr> ret =
     248            typedResult.strict_as<ast::ApplicationExpr>();
     249        return ast::deepCopy(ret);
     250    } else {
     251        auto untyped =
     252            new ast::UntypedExpr(location, new ast::NameExpr(location, "?[?]"),
     253                                 {std::move(arrAsVar), arg});
     254        auto typedResult = ResolvExpr::findVoidExpression(untyped, context);
     255
     256        ast::ptr<ast::ApplicationExpr> ret =
     257            typedResult.strict_as<ast::ApplicationExpr>();
     258        return ast::deepCopy(ret);
     259    }
    234260}
    235261
     
    250276        const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();
    251277        const std::string referredName = argAsVar->name;
    252         const ast::EnumInstType* argType =
    253             argAsVar->type.as<const ast::EnumInstType>();
    254         if (!argType) {
     278
     279        if (const ast::EnumInstType* argTypeAsEnumInst =
     280                argAsVar->type.as<const ast::EnumInstType>()) {
     281            const ast::EnumDecl* base = argTypeAsEnumInst->base;
     282            ResolvExpr::ResolveContext context{symtab, transUnit().global};
     283            // If resolvable as constant
     284            for (size_t i = 0; i < base->members.size(); i++) {
     285                if (base->members[i]->name == referredName) {
     286                    if (fname == "posE")
     287                        return ast::ConstantExpr::from_int(expr->location, i);
     288                    else if (fname == "labelE")
     289                        return ast::ConstantExpr::from_string(expr->location,
     290                                                              referredName);
     291                    else {
     292                        return getPseudoFuncApplication(
     293                            location, context, arg.get(), base, "values_");
     294                    }
     295                }
     296            }
     297
     298            if (fname == "labelE") {
     299                if (auto labelExpr = getPseudoFuncApplication(
     300                        location, context, arg.get(), base, "labels_")) {
     301                    return labelExpr;
     302                }
     303            } else if (fname == "valueE") {
     304                if (auto valueExpr = getPseudoFuncApplication(
     305                        location, context, arg.get(), base, "values_")) {
     306                    return valueExpr;
     307                }
     308            } else {  // it is position; replace itself
     309                return std::move(arg.get());
     310            }
     311        } else if (const ast::EnumPosType* argTypeAsPos =
     312                       argAsVar->type.as<const ast::EnumPosType>()) {
     313            const ast::EnumDecl* base = argTypeAsPos->instance->base;
     314            ResolvExpr::ResolveContext context{symtab, transUnit().global};
     315            if (fname == "labelE") {
     316                if (auto labelExpr = getPseudoFuncApplication(
     317                        location, context, arg.get(), base, "labels_")) {
     318                    return labelExpr;
     319                }
     320            } else if (fname == "valueE") {
     321                if (auto valueExpr = getPseudoFuncApplication(
     322                        location, context, arg.get(), base, "values_")) {
     323                    return valueExpr;
     324                }
     325            } else {  // it is position; replace itself
     326                return std::move(arg.get());
     327            }
     328        } else {
    255329            SemanticError(argAsVar,
    256330                          "Pseudo Enum Expression can only be used on an "
    257331                          "enumeration instance");
    258332        }
    259         const ast::EnumDecl* base = argType->base;
    260         ResolvExpr::ResolveContext context{symtab, transUnit().global};
    261         // If resolvable as constant
    262         for (size_t i = 0; i < base->members.size(); i++) {
    263             if (base->members[i]->name == referredName) {
    264                 if (fname == "posE")
    265                     return ast::ConstantExpr::from_int(expr->location, i);
    266                 else if (fname == "labelE")
    267                     return ast::ConstantExpr::from_string(expr->location,
    268                                                           referredName);
    269                 else {
    270                     return getPseudoFuncApplication(location, context, arg.get(),
    271                                                base, "values_");                   
    272                 }
    273 
    274             }
    275         }
    276 
    277         if (fname == "labelE") {
    278             if (auto labelExpr =
    279                     getPseudoFuncApplication(location, context, arg.get(), base, "labels_")) {
    280                 return labelExpr;
    281             }
    282         } else if (fname == "valueE") {
    283             if (auto valueExpr =
    284                     getPseudoFuncApplication(location, context, arg.get(), base, "values_")) {
    285                 return valueExpr;
    286             }
    287         } else { // it is position; replace itself
    288             return std::move( arg.get() );
    289         }
    290333    }
    291334    return expr;
    292335}
     336
     337ast::ptr<ast::Expr> reduceCastExpr(ast::ptr<ast::Expr> expr) {
     338    if (auto castExpr = expr.as<ast::CastExpr>()) {
     339        return reduceCastExpr(castExpr->arg);
     340    }
     341    return expr;
     342}
     343
     344struct ReplaceEnumInst final {
     345    const ast::Expr* postvisit(const ast::ApplicationExpr* expr) {
     346        auto fname = ast::getFunctionName(expr);
     347        if (fname != "?[?]") return expr;
     348        if (expr->args.size() != 2) return expr;
     349
     350        auto arg1AsVar =
     351            reduceCastExpr(expr->args.front()).as<ast::VariableExpr>();
     352        auto arg2AsVar =
     353            reduceCastExpr(expr->args.back()).as<ast::VariableExpr>();
     354
     355        if (!arg1AsVar || !arg2AsVar) return expr;
     356
     357        auto arg1Asecl = arg1AsVar->var.as<ast::ObjectDecl>();
     358        auto arg2Asecl = arg2AsVar->var.as<ast::ObjectDecl>();
     359
     360        if (!arg1Asecl || !arg2Asecl) return expr;
     361        auto arrInst = arg1Asecl->type.as<ast::ArrayType>();
     362        auto pointerInst = arg1Asecl->type.as<ast::PointerType>();
     363        if (!arrInst && !pointerInst) {
     364            return expr;
     365        }
     366        auto enumInst = arg2Asecl->type.as<ast::EnumInstType>();
     367        if (!enumInst) return expr;
     368
     369        const std::string arrName = arg1Asecl->name;
     370        if (arrName != getValueArrayName(enumInst->base->name)) return expr;
     371        ast::Pass<ReplaceEnumInstWithPos> replacer;
     372        auto rep = arg2Asecl->accept(replacer);
     373        if (!rep) return expr;
     374        auto mutObj =
     375            ast::mutate_field(arg2AsVar, &ast::VariableExpr::var, rep);
     376        auto mut = ast::mutate_field_index(expr, &ast::ApplicationExpr::args, 1,
     377                                           mutObj);
     378        return mut;
     379    }
     380};
    293381
    294382}  // namespace
     
    299387    ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit);
    300388    ast::Pass<ReplacePseudoFuncCore>::run(translationUnit);
     389    ast::Pass<ReplaceEnumInst>::run(translationUnit);
    301390}
    302391}  // namespace Validate
Note: See TracChangeset for help on using the changeset viewer.