source: src/Validate/ReplacePseudoFunc.cpp@ 3db78b89

Last change on this file since 3db78b89 was 544deb9, checked in by JiadaL <j82liang@…>, 20 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.