Changeset 0522ebe for src/Validate


Ignore:
Timestamp:
Feb 26, 2024, 3:49:23 AM (3 months ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
a4da45e
Parents:
c17dc80
Message:

Add EnumPosType? to type system

Location:
src/Validate
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/Validate/Autogen.cpp

    rc17dc80 r0522ebe  
    206206        ast::FunctionDecl * genLabelProto() const;
    207207        ast::FunctionDecl * genValueProto() const;
     208        // ast::FunctionDecl * genValueProto2() const;
    208209};
    209210
     
    790791}
    791792
     793// ast::FunctionDecl * EnumFuncGenerator::genValueProto2() const {
     794//      return genProto( "valueE",
     795//              { new ast::ObjectDecl( getLocation(), "_i", new ast::EnumPosType( new ast::EnumInstType( decl ) ) )},
     796//              { new ast::ObjectDecl( getLocation(), "_ret", ast::deepCopy( decl->base ) ) } );
     797// }
     798
    792799void EnumFuncGenerator::genAttrFuncForward() { 
    793800        if ( decl->base ) {
    794801                ast::FunctionDecl *(EnumFuncGenerator::*attrProtos[3])() const = {
    795802                        &EnumFuncGenerator::genPosProto, &EnumFuncGenerator::genLabelProto,
    796                         &EnumFuncGenerator::genValueProto };
     803                        &EnumFuncGenerator::genValueProto
     804                        // , &EnumFuncGenerator::genValueProto2
     805                        };
    797806                for ( auto & generator : attrProtos ) {
    798807                        produceForwardDecl( (this->*generator)() );
  • src/Validate/ReplacePseudoFunc.cpp

    rc17dc80 r0522ebe  
    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.