source: src/Validate/ReplacePseudoFunc.cpp @ 36e120a

Last change on this file since 36e120a was 544deb9, checked in by JiadaL <j82liang@…>, 5 months ago

Update ReplacePseudoFunc?, mostly the runtime lookup for attribute pseudo-function. It is imcomplete and returning dummy value

  • Property mode set to 100644
File size: 8.1 KB
Line 
1#include "ReplacePseudoFunc.hpp"
2
3#include <set>
4
5#include "AST/Decl.hpp"
6#include "AST/Inspect.hpp"
7#include "AST/Pass.hpp"
8#include "AST/Stmt.hpp"
9#include "Common/utility.h"
10#include "ResolvExpr/Resolver.h"
11#include "SymTab/Mangler.h"  // for Mangler
12namespace Validate {
13
14namespace {
15
16std::set<std::string> queryLabels;
17std::set<std::string> queryValues;
18
19struct FindGenEnumArray final : public ast::WithShortCircuiting {
20    void previsit(const ast::ApplicationExpr* enumDecl);
21};
22
23void FindGenEnumArray::previsit(const ast::ApplicationExpr* expr) {
24    auto fname = ast::getFunctionName(expr);
25    if (fname == "labelE" || fname == "valueE") {
26        if (expr->args.size() != 1) {
27            SemanticError(expr, "Position Expression only take one parameter");
28        }
29        const ast::VariableExpr* arg =
30            expr->args.front().as<const ast::VariableExpr>();
31        if (!arg) {
32            SemanticError(expr, "Unimplement Pseudo Function Cases");
33        }
34        const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();
35        const std::string referredName = argAsVar->name;
36        const ast::EnumInstType* argType =
37            argAsVar->type.as<const ast::EnumInstType>();
38        if (!argType) {
39            SemanticError(
40                argAsVar,
41                "Position can only be used on an enumeration instance");
42        }
43        ast::ptr<ast::EnumDecl> base = argType->base;
44        assert(base);
45        if (fname == "labelE") queryLabels.insert(base->name);
46        if (fname == "valueE") queryValues.insert(base->name);
47    }
48}
49
50struct PseudoFuncGenerateRoutine final : public ast::WithDeclsToAdd<>,
51                                         public ast::WithSymbolTable,
52                                         public ast::WithShortCircuiting {
53    void previsit(const ast::EnumDecl* enumDecl);
54};
55
56void PseudoFuncGenerateRoutine::previsit(const ast::EnumDecl* enumDecl) {
57    visit_children = false;
58    const CodeLocation& location = enumDecl->location;
59    if (enumDecl->members.size() == 0 || !enumDecl->base) return;
60
61    std::vector<ast::ptr<ast::Init>> inits;
62    std::vector<ast::ptr<ast::Init>> labels;
63    for (const ast::Decl* mem : enumDecl->members) {
64        auto memAsObjectDecl = dynamic_cast<const ast::ObjectDecl*>(mem);
65        inits.emplace_back(memAsObjectDecl->init);
66        labels.emplace_back(new ast::SingleInit(
67            location, ast::ConstantExpr::from_string(location, mem->name)));
68    }
69    if (queryValues.count(enumDecl->name)) {
70        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);
78        symtab.addId(values);
79        values->mangleName = Mangle::mangle(values);
80        declsToAddAfter.push_back(values);
81    }
82    if (queryLabels.count(enumDecl->name)) {
83        auto label_strings = new ast::ListInit(location, std::move(labels));
84        auto label_arr = new ast::ObjectDecl(
85            location, "labels_" + enumDecl->name,
86            new ast::ArrayType(
87                new ast::PointerType(new ast::BasicType{ast::BasicType::Char}),
88                ast::ConstantExpr::from_int(location, enumDecl->members.size()),
89                ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim),
90            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
97struct ReplacePseudoFuncCore : public ast::WithShortCircuiting,
98                               public ast::WithSymbolTable,
99                               public ast::WithConstTranslationUnit {
100    ast::Expr const* postvisit(ast::ApplicationExpr const* decl);
101};
102
103ast::Expr const* ReplacePseudoFuncCore::postvisit(
104    ast::ApplicationExpr const* expr) {
105    auto fname = ast::getFunctionName(expr);
106    auto location = expr->location;
107    if (fname == "posE" || fname == "valueE" || fname == "labelE") {
108        if (expr->args.size() != 1) {
109            SemanticError(expr,
110                          "Pseudo Enum Expression only take one parameter");
111        }
112        ast::ptr<ast::VariableExpr> arg =
113            expr->args.front().as<const ast::VariableExpr>();
114        if (!arg) {
115            SemanticError(expr, "Unimplement Pseudo Function Cases");
116        }
117        const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();
118        const std::string referredName = argAsVar->name;
119        const ast::EnumInstType* argType =
120            argAsVar->type.as<const ast::EnumInstType>();
121        if (!argType) {
122            SemanticError(argAsVar,
123                          "Pseudo Enum Expression can only be used on an "
124                          "enumeration instance");
125        }
126        const ast::EnumDecl* base = argType->base;
127        for (size_t i = 0; i < base->members.size(); i++) {
128            if (base->members[i]->name == referredName) {
129                if (fname == "posE")
130                    return ast::ConstantExpr::from_int(expr->location, i);
131                else if (fname == "labelE")
132                    return ast::ConstantExpr::from_string(expr->location,
133                                                          referredName);
134                else
135                    return new ast::TypeExpr(expr->location, argType);
136            }
137        }
138
139        ResolvExpr::ResolveContext context{symtab, transUnit().global};
140
141        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            }
187        }
188    }
189    return expr;
190}
191
192}  // namespace
193
194void replacePseudoFunc(ast::TranslationUnit& translationUnit) {
195    ast::Pass<FindGenEnumArray>::run(translationUnit);
196    ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit);
197    ast::Pass<ReplacePseudoFuncCore>::run(translationUnit);
198}
199}  // namespace Validate
Note: See TracBrowser for help on using the repository browser.