Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Validate/ReplacePseudoFunc.cpp

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