Changeset c75b30a


Ignore:
Timestamp:
Jan 31, 2024, 6:25:02 PM (3 months ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
32490deb
Parents:
16afb2a
Message:

Introduce posE, valueE, labelE pseudo language to the language. Rework the internal representation of enumeration.

Location:
src
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cpp

    r16afb2a rc75b30a  
    331331        extension( decl );
    332332        auto members = decl->members;
    333         if ( decl->base && !members.empty() ) {
    334                 long long curVal = 0;
    335                 for ( auto member : members ) {
    336                         auto obj = member.strict_as<ast::ObjectDecl>();
    337                         output << "static ";
    338                         output << genType( decl->base, mangleName( obj ), options );
    339                         genEnumInitializer( visitor, decl->base, output, obj->init, &curVal, options );
    340                         output << ";" << endl;
    341                 }
    342         } else {
     333        // if ( decl->base && !members.empty() ) {
     334        //      long long curVal = 0;
     335        //      for ( auto member : members ) {
     336        //              auto obj = member.strict_as<ast::ObjectDecl>();
     337        //              output << "static ";
     338        //              output << genType( decl->base, mangleName( obj ), options );
     339        //              genEnumInitializer( visitor, decl->base, output, obj->init, &curVal, options );
     340        //              output << ";" << endl;
     341        //      }
     342        // } else {
    343343                output << "enum ";
    344344                genAttributes( decl->attributes );
     
    353353                                auto obj = member.strict_as<ast::ObjectDecl>();
    354354                                output << indent << mangleName( obj );
    355                                 if ( obj->init ) {
     355                                if ( !decl->base && obj->init ) {
    356356                                        output << " = ";
    357357                                        obj->init->accept( *visitor );
     
    363363                        output << indent << "}";
    364364                }
    365         }
     365        // }
    366366}
    367367
  • src/CodeGen/GenType.cc

    r16afb2a rc75b30a  
    228228
    229229void GenType::postvisit( ast::EnumInstType const * type ) {
    230         if ( type->base && type->base->base ) {
    231                 result = genType( type->base->base, result, options );
    232         } else {
     230        // if ( type->base && type->base->base ) {
     231        //      result = genType( type->base->base, result, options );
     232        // } else {
    233233                result = type->name + " " + result;
    234234                if ( options.genC ) {
    235235                        result = "enum " + result;
    236236                }
    237         }
     237        // }
    238238        handleQualifiers( type );
    239239}
  • src/GenPoly/Lvalue.cpp

    r16afb2a rc75b30a  
    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        }
     
    161175ast::Expr const * FixIntrinsicResults::postvisit(
    162176                ast::ApplicationExpr const * expr ) {
    163         if ( skip == SkipInProgress || !isIntrinsicReference( expr ) ) {
     177
     178        if ( skip == SkipInProgress || !isIntrinsicReference( expr ) || isGeneratedInstrinct( expr ) ) {
    164179                return expr;
    165180        }
  • src/ResolvExpr/CandidateFinder.cpp

    r16afb2a rc75b30a  
    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                        }
    893907                }
    894908        }
     
    961975
    962976                                        if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer);                                             
    963                                         // else if (const ast::EnumInstType * enumInst = argType.as<ast::EnumInstType>()) {
    964                                         //      const ast::EnumDecl * enumDecl = enumInst->base; // Here
    965                                         //      if ( const ast::Type* enumType = enumDecl->base ) {
    966                                         //              // instance of enum (T) is a instance of type (T)
    967                                         //              funcFinder.otypeKeys.insert(Mangle::mangle(enumType, Mangle::NoGenericParams | Mangle::Type));
    968                                         //      } else {
    969                                         //              // instance of an untyped enum is techically int
    970                                         //              funcFinder.otypeKeys.insert(Mangle::mangle(enumDecl, Mangle::NoGenericParams | Mangle::Type));
    971                                         //      }
    972                                         // }
    973977                                        else funcFinder.otypeKeys.insert(Mangle::mangle(argType, Mangle::NoGenericParams | Mangle::Type));
    974978                                }
     
    13991403                // not sufficient to just pass `variableExpr` here, type might have changed since
    14001404                // creation
    1401                 addCandidate(
    1402                         new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
     1405                if ( auto obj =  dynamic_cast<const ast::ObjectDecl *>( variableExpr->var.get() )) {
     1406                        if ( auto enumInstType = dynamic_cast<const ast::EnumInstType *>( obj->type.get() ) ) {
     1407                                if ( enumInstType->base && enumInstType->base->base ) {
     1408                                        const CodeLocation & location = variableExpr->location;
     1409                                        auto ids = symtab.lookupId( "valueE" );
     1410                                                for ( ast::SymbolTable::IdData & id : ids ) {
     1411                                                        if ( auto func = id.id.as<ast::FunctionDecl>() ) {
     1412                                                                if ( func->params.size() == 1 ) {
     1413                                                                        ast::ptr<ast::DeclWithType> valueEParam = func->params.front();
     1414                                                                        auto valueEParamType = valueEParam->get_type();
     1415                                                                        ast::OpenVarSet funcOpen;
     1416                                                                        ast::AssertionSet funcNeed, funcHave;
     1417                                                                        ast::TypeEnvironment funcEnv{ tenv };
     1418                                                                        ast::ptr<ast::Type> common;
     1419                                                                        if ( unifyInexact( valueEParamType, enumInstType, funcEnv, funcNeed, funcHave, funcOpen, WidenMode{ true, true }, common ) ) {
     1420                                                                                auto appl = new ast::ApplicationExpr( location,
     1421                                                                                        ast::VariableExpr::functionPointer( location,  func), { variableExpr } );
     1422                                                                                // addCandidate( appl, copy( tenv ),  );
     1423                                                                                Candidate cand {appl, copy( tenv )};
     1424                                                                                addCandidate( cand, appl, Cost::safe );
     1425                                                                        }
     1426                                                                }
     1427                                                        }
     1428                                                }
     1429                                }
     1430                       
     1431                        }
     1432                }
     1433                addCandidate( variableExpr, tenv );
     1434               
    14031435        }
    14041436
  • src/ResolvExpr/ConversionCost.cc

    r16afb2a rc75b30a  
    279279                conversionCostFromBasicToBasic( basicType, dstAsBasic );
    280280        } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
    281                 const ast::EnumDecl * enumDecl = enumInst->base.get();
    282                 if ( enumDecl->isTyped && !enumDecl->base.get() ) {
    283                         cost = Cost::infinity;
    284                 } else if ( const ast::Type * enumType = enumDecl->base.get() ) {
    285                         if ( const ast::BasicType * enumTypeAsBasic = dynamic_cast<const ast::BasicType *>(enumType) ) {
    286                                 conversionCostFromBasicToBasic( basicType, enumTypeAsBasic );
    287                         } else {
    288                                 cost = Cost::infinity;
    289                         }
     281                auto enumDecl = enumInst->base;
     282                if ( auto baseType = enumDecl->base.get() ) {
     283                        cost = costCalc( basicType, baseType, srcIsLvalue, symtab, env );
     284                        cost.incUnsafe();
    290285                } else {
    291286            cost = Cost::unsafe;
     
    367362
    368363void ConversionCost::postvisit( const ast::EnumInstType * enumInstType ) {
    369         const ast::EnumDecl * baseEnum = enumInstType->base;
    370         if ( const ast::Type * baseType = baseEnum->base ) {
    371                 costCalc( baseType, dst, srcIsLvalue, symtab, env );
    372         } else {
    373                 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
    374                 cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
    375         }
     364        //      const ast::EnumDecl * baseEnum = enumInstType->base;
     365        // if ( const ast::Type * baseType = baseEnum->base ) {
     366        //      costCalc( baseType, dst, srcIsLvalue, symtab, env );
     367        // } else {
     368        static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
     369        cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
     370        // }
    376371        if ( cost < Cost::unsafe ) {
    377372                cost.incSafe();
  • src/ResolvExpr/Unify.cc

    r16afb2a rc75b30a  
    7373                ast::Type * newFirst  = shallowCopy( first  );
    7474                ast::Type * newSecond = shallowCopy( second );
    75                 if ( auto temp = dynamic_cast<const ast::EnumInstType *>(first) ) {
    76                         if ( !dynamic_cast< const ast::EnumInstType * >( second ) ) {
    77                                 const ast::EnumDecl * baseEnum = dynamic_cast<const ast::EnumDecl *>(temp->base.get());
    78                                 if ( auto t = baseEnum->base.get() ) {
    79                                         newFirst = ast::shallowCopy( t );
    80                                 }
    81                         }
    82                 } else if ( auto temp = dynamic_cast<const ast::EnumInstType *>(second) ) {
    83                         const ast::EnumDecl * baseEnum = dynamic_cast<const ast::EnumDecl *>(temp->base.get());
    84                         if ( auto t = baseEnum->base.get() ) {
    85                                 newSecond = ast::shallowCopy( t );
    86                         }
    87                 }
    8875
    8976                newFirst ->qualifiers = {};
  • src/Validate/Autogen.cpp

    r16afb2a rc75b30a  
    197197
    198198        bool shouldAutogen() const final { return true; }
     199        void genAttrFuncForward();
     200        void __attribute__ ((unused)) genDualFuncs();
    199201private:
    200202        void genFuncBody( ast::FunctionDecl * decl ) final;
    201203        void genFieldCtors() final;
    202204        const ast::Decl * getDecl() const final { return decl; }
     205
     206        ast::ObjectDecl * dualDstParam() const;
     207
     208        ast::FunctionDecl * genPosProto() const;
     209        ast::FunctionDecl * genLabelProto() const;
     210        ast::FunctionDecl * genValueProto() const;
     211
     212        ast::FunctionDecl * genCopyEnumToDualProto() const;
     213        ast::FunctionDecl * genAssignEnumToDualProto() const;
     214
     215        void genDualBody( ast::FunctionDecl * decl );
    203216};
    204217
     
    238251// --------------------------------------------------------------------------
    239252void AutogenerateRoutines::previsit( const ast::EnumDecl * enumDecl ) {
    240         // Must visit children (enum constants) to add them to the symbol table.
    241253        if ( !enumDecl->body ) return;
    242 
    243         // if ( auto enumBaseType = enumDecl->base ) {
    244         //      if ( auto enumBaseTypeAsStructInst = dynamic_cast<const ast::StructInstType *>(enumBaseType.get()) ) {
    245         //              const ast::StructDecl * structDecl = enumBaseTypeAsStructInst->base.get();
    246         //              this->previsit( structDecl );
    247         //      }
    248         // }
    249254
    250255        ast::EnumInstType enumInst( enumDecl->name );
    251256        enumInst.base = enumDecl;
    252257        EnumFuncGenerator gen( enumDecl, &enumInst, functionNesting );
     258        if ( enumDecl->base ) {
     259                gen.genAttrFuncForward();
     260                // gen.genDualFuncs();
     261        }
    253262        gen.generateAndAppendFunctions( declsToAddAfter );
    254263}
     
    742751                 * returns to zero.
    743752                 */
     753                auto dstExpr = new ast::VariableExpr( location, dstParam );
     754                const ast::Expr * srcExpr;
     755                if ( decl->base ) {
     756                        srcExpr = new ast::ApplicationExpr( location,
     757                        ast::VariableExpr::functionPointer( location, genPosProto() ),
     758                        {
     759                                new ast::VariableExpr( location, srcParam )
     760                        }
     761                        );
     762                } else {
     763                        srcExpr = new ast::VariableExpr( location, srcParam );
     764                }
     765
    744766                auto callExpr = new ast::ApplicationExpr( location,
    745767                        ast::VariableExpr::functionPointer( location, functionDecl ),
    746768                        {
    747                                 new ast::VariableExpr( location, dstParam ),
    748                                 new ast::VariableExpr( location, srcParam ),
     769                                dstExpr,
     770                                srcExpr,
    749771                        }
    750772                );
    751                 // auto fname = ast::getFunctionName( callExpr );
    752                 // if (fname == "posE" ) {
    753                 //      std::cerr << "Found posE autogen" << std::endl;
    754                 // }
     773
    755774                functionDecl->stmts = new ast::CompoundStmt( location,
    756775                        { new ast::ExprStmt( location, callExpr ) }
     
    768787                        forwards.back().get_and_mutate() );
    769788                addUnusedAttribute( fwd->params.front() );
     789        }
     790}
     791
     792ast::FunctionDecl * EnumFuncGenerator::genPosProto() const {
     793        return genProto( "posE",
     794                { new ast::ObjectDecl( getLocation(), "_i",
     795                new ast::EnumInstType( decl ) )},
     796                { new ast::ObjectDecl( getLocation(), "_ret",
     797                new ast::BasicType{ ast::BasicType::UnsignedInt } )} );
     798}
     799
     800ast::FunctionDecl * EnumFuncGenerator::genLabelProto() const {
     801        return genProto( "labelE",
     802                { new ast::ObjectDecl( getLocation(), "_i",
     803                new ast::EnumInstType( decl ) ) },
     804                { new ast::ObjectDecl( getLocation(), "_ret",
     805                new ast::PointerType( new ast::BasicType{ ast::BasicType::Char } ) ) } );
     806}
     807
     808ast::FunctionDecl * EnumFuncGenerator::genValueProto() const {
     809        return genProto( "valueE",
     810                { new ast::ObjectDecl( getLocation(), "_i", new ast::EnumInstType( decl ) )},
     811                { new ast::ObjectDecl( getLocation(), "_ret", ast::deepCopy( decl->base ) ) } );
     812}
     813
     814void EnumFuncGenerator::genAttrFuncForward() { 
     815        if ( decl->base ) {
     816                ast::FunctionDecl *(EnumFuncGenerator::*attrProtos[3])() const = {
     817                        &EnumFuncGenerator::genPosProto, &EnumFuncGenerator::genLabelProto,
     818                        &EnumFuncGenerator::genValueProto };
     819                for ( auto & generator : attrProtos ) {
     820                        produceForwardDecl( (this->*generator)() );
     821                }
     822        }
     823}
     824
     825ast::ObjectDecl * EnumFuncGenerator::dualDstParam() const {
     826        auto base = decl->base;
     827        assert( base );
     828        return new ast::ObjectDecl( getLocation(), "_dst",
     829                new ast::ReferenceType( ast::deepCopy( base ) ) );
     830}
     831
     832// void ?{}(T & _dst, enum E _src )
     833ast::FunctionDecl * EnumFuncGenerator::genCopyEnumToDualProto() const {
     834        return genProto( "?{}", { dualDstParam(), srcParam() }, {} );
     835}
     836
     837// T ?{}(T & _dst, enum E _src )
     838ast::FunctionDecl * EnumFuncGenerator::genAssignEnumToDualProto() const {
     839        auto retval = dualDstParam();
     840        retval->name = "_ret";
     841        return genProto( "?=?", { dualDstParam(), srcParam() }, { retval });
     842}
     843
     844void EnumFuncGenerator::genDualBody( ast::FunctionDecl * functionDecl ) {
     845        assert( decl->base );
     846        const CodeLocation& location = functionDecl->location;
     847        auto & params = functionDecl->params;
     848       
     849        assert( 2 == params.size() );
     850        auto dstParam = params.front().strict_as<ast::ObjectDecl>();
     851        auto srcParam = params.back().strict_as<ast::ObjectDecl>();
     852
     853        auto dstExpr = new ast::VariableExpr( location, dstParam );
     854
     855        auto srcExpr = new ast::ApplicationExpr( location,
     856                ast::VariableExpr::functionPointer( location, genValueProto() ),
     857                {
     858                        new ast::VariableExpr( location, srcParam )
     859                });
     860        auto callExpr = new ast::ApplicationExpr( location,
     861                ast::VariableExpr::functionPointer( location, functionDecl ),
     862                { dstExpr, srcExpr } );
     863        functionDecl->stmts = new ast::CompoundStmt( location,
     864                { new ast::ExprStmt( location, callExpr)} );
     865}
     866
     867void EnumFuncGenerator::genDualFuncs() {
     868        assert( decl->base );
     869        ast::FunctionDecl *(EnumFuncGenerator::*dualProtos[2])() const = {
     870                        &EnumFuncGenerator::genCopyEnumToDualProto,
     871                        &EnumFuncGenerator::genAssignEnumToDualProto };
     872        for ( auto & generator : dualProtos ) {
     873                ast::FunctionDecl * decl = (this->*generator)();
     874                produceForwardDecl( decl );
     875                genDualBody( decl );
     876                if ( CodeGen::isAssignment( decl->name ) ) {
     877                        appendReturnThis( decl );
     878                }
     879                produceDecl( decl );
    770880        }
    771881}
  • src/Validate/ReplacePseudoFunc.cpp

    r16afb2a rc75b30a  
    1717std::set<std::string> queryValues;
    1818
     19struct WrapEnumValueExpr final : public ast::WithShortCircuiting,
     20                                 public ast::WithSymbolTable,
     21                                 public ast::WithConstTranslationUnit {
     22    void previsit(const ast::DeclStmt* expr);
     23    void previsit(const ast::ApplicationExpr* expr);
     24    void previsit(const ast::CastExpr* expr);
     25
     26    ast::Expr const* postvisit(const ast::VariableExpr* expr);
     27};
     28
    1929struct FindGenEnumArray final : public ast::WithShortCircuiting {
    2030    void previsit(const ast::ApplicationExpr* enumDecl);
    2131};
     32
     33struct PseudoFuncGenerateRoutine final : public ast::WithDeclsToAdd<>,
     34                                         public ast::WithSymbolTable,
     35                                         public ast::WithShortCircuiting {
     36    void previsit(const ast::EnumDecl* enumDecl);
     37};
     38
     39struct ReplacePseudoFuncCore : public ast::WithShortCircuiting,
     40                               public ast::WithSymbolTable,
     41                               public ast::WithConstTranslationUnit {
     42    ast::Expr const* postvisit(ast::ApplicationExpr const* decl);
     43};
     44
     45void WrapEnumValueExpr::previsit(const ast::ApplicationExpr* expr) {
     46
     47    auto varExpr = expr->func.as<ast::VariableExpr>();
     48    auto fname = ast::getFunctionName(expr);
     49        if ( !varExpr || varExpr->var->linkage == ast::Linkage::Intrinsic ) {
     50        if ( fname == "?{}" || fname == "?=?" )
     51                    visit_children = false;
     52        }
     53
     54    if (fname == "labelE" || fname == "valueE" || fname == "posE")
     55        visit_children = false;
     56}
     57
     58void WrapEnumValueExpr::previsit(const ast::DeclStmt*) {
     59    visit_children = false;
     60}
     61
     62void WrapEnumValueExpr::previsit(const ast::CastExpr* expr) {
     63    if (expr->result && expr->result.as<ast::ReferenceType>()) {
     64        visit_children = false;
     65    }
     66}
     67
     68ast::Expr const* WrapEnumValueExpr::postvisit(const ast::VariableExpr* expr) {
     69    visit_children = false;
     70    if (!expr->result) {
     71        return expr;
     72    }
     73    if (auto enumInst = expr->result.as<ast::EnumInstType>()) {
     74        if (enumInst->base && enumInst->base->base) {
     75            auto untyped = new ast::UntypedExpr(
     76                expr->location, new ast::NameExpr(expr->location, "valueE"),
     77                {new ast::VariableExpr(*expr)});
     78            ResolvExpr::ResolveContext context{symtab, transUnit().global};
     79            auto result = ResolvExpr::findVoidExpression(untyped, context);
     80            if (result.get()) {
     81                ast::ptr<ast::ApplicationExpr> ret =
     82                    result.strict_as<ast::ApplicationExpr>();
     83                return new ast::ApplicationExpr(*ret);
     84            }
     85        }
     86    }
     87    return expr;
     88}
    2289
    2390void FindGenEnumArray::previsit(const ast::ApplicationExpr* expr) {
     
    48115}
    49116
    50 struct PseudoFuncGenerateRoutine final : public ast::WithDeclsToAdd<>,
    51                                          public ast::WithSymbolTable,
    52                                          public ast::WithShortCircuiting {
    53     void previsit(const ast::EnumDecl* enumDecl);
    54 };
    55 
    56117void PseudoFuncGenerateRoutine::previsit(const ast::EnumDecl* enumDecl) {
    57118    visit_children = false;
     
    67128            location, ast::ConstantExpr::from_string(location, mem->name)));
    68129    }
     130    // Values only
    69131    if (queryValues.count(enumDecl->name)) {
    70132        auto init = new ast::ListInit(location, std::move(inits));
    71         auto values = new ast::ObjectDecl(
    72             location, "values_" + enumDecl->name,
    73             new ast::ArrayType(
    74                 enumDecl->base,
    75                 ast::ConstantExpr::from_int(location, enumDecl->members.size()),
    76                 ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim),
    77             init, ast::Storage::Static, ast::Linkage::AutoGen);
     133        const ast::ArrayType* arrT = new ast::ArrayType(
     134            enumDecl->base,
     135            ast::ConstantExpr::from_int(location, enumDecl->members.size()),
     136            ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim);
     137        ast::ObjectDecl* values = new ast::ObjectDecl(
     138            location, "values_" + enumDecl->name, arrT, init,
     139            ast::Storage::Static, ast::Linkage::AutoGen);
    78140        symtab.addId(values);
    79141        values->mangleName = Mangle::mangle(values);
     
    82144    if (queryLabels.count(enumDecl->name)) {
    83145        auto label_strings = new ast::ListInit(location, std::move(labels));
    84         auto label_arr = new ast::ObjectDecl(
     146        auto labels = new ast::ObjectDecl(
    85147            location, "labels_" + enumDecl->name,
    86148            new ast::ArrayType(
     
    89151                ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim),
    90152            label_strings, ast::Storage::Static, ast::Linkage::AutoGen);
    91         symtab.addId(label_arr);
    92         label_arr->mangleName = Mangle::mangle(label_arr);
    93         declsToAddAfter.push_back(label_arr);
    94     }
    95 }
    96 
    97 struct ReplacePseudoFuncCore : public ast::WithShortCircuiting,
    98                                public ast::WithSymbolTable,
    99                                public ast::WithConstTranslationUnit {
    100     ast::Expr const* postvisit(ast::ApplicationExpr const* decl);
    101 };
     153        symtab.addId(labels);
     154        labels->mangleName = Mangle::mangle(labels);
     155        declsToAddAfter.push_back(labels);
     156    }
     157}
     158
     159ast::ApplicationExpr const* getPseudoFuncApplication(
     160    const CodeLocation location, ResolvExpr::ResolveContext context,
     161    const ast::VariableExpr* arg, const ast::EnumDecl* base, const std::string & name) {
     162    ast::Expr* toResolve = new ast::NameExpr(location, name + base->name);
     163    auto result = ResolvExpr::findVoidExpression(toResolve, context);
     164    assert(result.get());
     165    auto arrAsVar = result.strict_as<ast::VariableExpr>();
     166    auto untyped = new ast::UntypedExpr(
     167        location, new ast::NameExpr(location, "?[?]"),
     168        {new ast::VariableExpr(*arrAsVar), new ast::VariableExpr(*arg)});
     169    auto typedResult = ResolvExpr::findVoidExpression(untyped, context);
     170
     171    ast::ptr<ast::ApplicationExpr> ret =
     172        typedResult.strict_as<ast::ApplicationExpr>();
     173    return ast::deepCopy(ret);
     174}
    102175
    103176ast::Expr const* ReplacePseudoFuncCore::postvisit(
     
    125198        }
    126199        const ast::EnumDecl* base = argType->base;
     200        ResolvExpr::ResolveContext context{symtab, transUnit().global};
     201        // If resolvable as constant
    127202        for (size_t i = 0; i < base->members.size(); i++) {
    128203            if (base->members[i]->name == referredName) {
     
    133208                                                          referredName);
    134209                else
    135                     return new ast::TypeExpr(expr->location, argType);
    136             }
    137         }
    138 
    139         ResolvExpr::ResolveContext context{symtab, transUnit().global};
     210                    return getPseudoFuncApplication(location, context, arg.get(),
     211                                               base, "values_");
     212            }
     213        }
    140214
    141215        if (fname == "labelE") {
    142             ast::Expr* toResolve =
    143                 new ast::NameExpr(expr->location, "labels_" + base->name);
    144             auto result = ResolvExpr::findVoidExpression(toResolve, context);
    145             if (result.get()) {
    146                 auto arrAsVar = result.strict_as<ast::VariableExpr>();
    147                 auto untyped = new ast::UntypedExpr(
    148                     location, new ast::NameExpr(location, "?[?]"),
    149                     {new ast::VariableExpr(*arrAsVar),
    150                      ast::ConstantExpr::from_int(
    151                          location,
    152                          0)});  /// TODO: dummy value.
    153                                 /// To make it works need to change the unifier
    154 
    155                 auto typedResult =
    156                     ResolvExpr::findVoidExpression(untyped, context);
    157                 if (result.get()) {
    158                     ast::ptr<ast::ApplicationExpr> ret =
    159                         typedResult.strict_as<ast::ApplicationExpr>();
    160                     return new ast::ApplicationExpr(*ret);
    161                 }
    162             }
    163         }
    164        
    165         if (fname == "valueE") {
    166             ast::Expr* toResolve =
    167                 new ast::NameExpr(expr->location, "values_" + base->name);
    168             auto result = ResolvExpr::findVoidExpression(toResolve, context);
    169             if (result.get()) {
    170                 auto arrAsVar = result.strict_as<ast::VariableExpr>();
    171                 auto untyped = new ast::UntypedExpr(
    172                     location, new ast::NameExpr(location, "?[?]"),
    173                     {new ast::VariableExpr(*arrAsVar),
    174                      ast::ConstantExpr::from_int(
    175                          location,
    176                          0)});  /// TODO: dummy value.
    177                                 /// To make it works need to change the unifier
    178 
    179                 auto typedResult =
    180                     ResolvExpr::findVoidExpression(untyped, context);
    181                 if (result.get()) {
    182                     ast::ptr<ast::ApplicationExpr> ret =
    183                         typedResult.strict_as<ast::ApplicationExpr>();
    184                     return new ast::ApplicationExpr(*ret);
    185                 }
    186             }
     216            if (auto labelExpr =
     217                    getPseudoFuncApplication(location, context, arg.get(), base, "labels_")) {
     218                return labelExpr;
     219            }
     220        } else if (fname == "valueE") {
     221            if (auto valueExpr =
     222                    getPseudoFuncApplication(location, context, arg.get(), base, "values_")) {
     223                return valueExpr;
     224            }
     225        } else { // it is position; replace itself
     226            return std::move( arg.get() );
    187227        }
    188228    }
     
    193233
    194234void replacePseudoFunc(ast::TranslationUnit& translationUnit) {
     235    ast::Pass<WrapEnumValueExpr>::run(translationUnit);
    195236    ast::Pass<FindGenEnumArray>::run(translationUnit);
    196237    ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit);
Note: See TracChangeset for help on using the changeset viewer.