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

Reimplement the resolution of Enum instance type

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Validate/ReplacePseudoFunc.cpp

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