source: src/Validate/ReplacePseudoFunc.cpp@ f5212ca

Last change on this file since f5212ca was 76fe046, checked in by JiadaL <j82liang@…>, 19 months ago

Remove conversion part of the EnumPosType. It can be resolved by the current unifier

  • Property mode set to 100644
File size: 18.5 KB
RevLine 
[544deb9]1#include "ReplacePseudoFunc.hpp"
2
3#include <set>
4
[ac939461]5#include "AST/Decl.hpp"
[544deb9]6#include "AST/Inspect.hpp"
[ac939461]7#include "AST/Pass.hpp"
[0522ebe]8#include "AST/Print.hpp"
[ac939461]9#include "AST/Stmt.hpp"
10#include "Common/utility.h"
[0522ebe]11#include "ResolvExpr/CandidateFinder.hpp"
[544deb9]12#include "ResolvExpr/Resolver.h"
[a55ebcc]13#include "SymTab/Mangler.h"
14
[ac939461]15namespace Validate {
16
17namespace {
18
[544deb9]19std::set<std::string> queryLabels;
20std::set<std::string> queryValues;
21
[0522ebe]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
[a55ebcc]37// struct AutoInit {
38// ast::EnumDecl const* postvisit( const ast::EnumDecl* expr );
39// };
40
[c75b30a]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);
[0522ebe]47 void previsit(const ast::VariableExpr*) { visit_children = false; }
[c75b30a]48
49 ast::Expr const* postvisit(const ast::VariableExpr* expr);
50};
51
[544deb9]52struct FindGenEnumArray final : public ast::WithShortCircuiting {
53 void previsit(const ast::ApplicationExpr* enumDecl);
[ac939461]54};
[544deb9]55
[c75b30a]56struct PseudoFuncGenerateRoutine final : public ast::WithDeclsToAdd<>,
57 public ast::WithSymbolTable,
[a55ebcc]58 public ast::WithShortCircuiting,
59 public ast::WithConstTranslationUnit {
[c75b30a]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
[a55ebcc]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// }
[c75b30a]77
[a55ebcc]78void WrapEnumValueExpr::previsit(const ast::ApplicationExpr* expr) {
[c75b30a]79 auto varExpr = expr->func.as<ast::VariableExpr>();
80 auto fname = ast::getFunctionName(expr);
[0522ebe]81 if (!varExpr || varExpr->var->linkage == ast::Linkage::Intrinsic) {
82 if (fname == "?{}" || fname == "?=?") visit_children = false;
83 }
[c75b30a]84
[bbf2cb1]85 if (fname == "labelE" || fname == "valueE" || fname == "posE" ||
86 fname == "pred" || fname == "succ") {
[c75b30a]87 visit_children = false;
[a55ebcc]88 }
[c75b30a]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"),
[0522ebe]109 {std::move(expr)});
[c75b30a]110 ResolvExpr::ResolveContext context{symtab, transUnit().global};
111 auto result = ResolvExpr::findVoidExpression(untyped, context);
[a55ebcc]112 ast::ptr<ast::ApplicationExpr> ret =
[0522ebe]113 result.strict_as<ast::ApplicationExpr>();
114 return ast::deepCopy(ret);
[c75b30a]115 }
116 }
117 return expr;
118}
119
[544deb9]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 }
[ac939461]145}
146
[0522ebe]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)) {
[a55ebcc]152 auto prevInitExpr = prevInit->value;
[0522ebe]153 if (auto constInit = prevInitExpr.as<ast::ConstantExpr>()) {
[a55ebcc]154 // Assume no string literal for now
155 return new ast::SingleInit(
[0522ebe]156 location, ast::ConstantExpr::from_int(
157 location, constInit->intValue() + 1));
[a55ebcc]158 } else {
159 auto untypedThisInit = new ast::UntypedExpr(
[0522ebe]160 location, new ast::NameExpr(location, "?++"), {prevInitExpr});
161 auto typedInit = ResolvExpr::findSingleExpression(untypedThisInit,
162 type, context);
163 return new ast::SingleInit(location, typedInit);
[a55ebcc]164 }
165 }
[0522ebe]166 SemanticError(prev, "Auto Init a List is not implemented");
[a55ebcc]167 return prev;
168}
169
[544deb9]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;
[a55ebcc]177 auto type = enumDecl->base;
178
[0522ebe]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);
[a55ebcc]185 } else {
[0522ebe]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)));
[a55ebcc]190 } else {
[0522ebe]191 inits.emplace_back(getAutoInit(
192 location, enumDecl->base,
193 ResolvExpr::ResolveContext{symtab, transUnit().global},
194 inits.at(i - 1).as<ast::SingleInit>()));
[a55ebcc]195 }
196 }
[544deb9]197 labels.emplace_back(new ast::SingleInit(
[0522ebe]198 location, ast::ConstantExpr::from_string(location, mem->name)));
199 }
[544deb9]200 if (queryValues.count(enumDecl->name)) {
201 auto init = new ast::ListInit(location, std::move(inits));
[c75b30a]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);
[544deb9]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));
[c75b30a]215 auto labels = new ast::ObjectDecl(
[544deb9]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);
[c75b30a]222 symtab.addId(labels);
223 labels->mangleName = Mangle::mangle(labels);
224 declsToAddAfter.push_back(labels);
[544deb9]225 }
226}
227
[bbf2cb1]228ast::ApplicationExpr const* resolveAttributeFunctions(
[c75b30a]229 const CodeLocation location, ResolvExpr::ResolveContext context,
[0522ebe]230 const ast::VariableExpr* arg, const ast::EnumDecl* base,
231 const std::string& name) {
[c75b30a]232 ast::Expr* toResolve = new ast::NameExpr(location, name + base->name);
[0522ebe]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);
[bbf2cb1]243 mutatedArg = ast::mutate_field(mutatedArg, &ast::VariableExpr::result,
244 mutatedArg->var->get_type());
[0522ebe]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 }
[c75b30a]262}
[544deb9]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");
[ac939461]272 }
[544deb9]273 ast::ptr<ast::VariableExpr> arg =
274 expr->args.front().as<const ast::VariableExpr>();
275 if (!arg) {
276 SemanticError(expr, "Unimplement Pseudo Function Cases");
[ac939461]277 }
[544deb9]278 const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();
[ac939461]279 const std::string referredName = argAsVar->name;
[a55ebcc]280
[0522ebe]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 {
[bbf2cb1]294 return resolveAttributeFunctions(
[0522ebe]295 location, context, arg.get(), base, "values_");
296 }
297 }
[544deb9]298 }
299
[0522ebe]300 if (fname == "labelE") {
[bbf2cb1]301 if (auto labelExpr = resolveAttributeFunctions(
[0522ebe]302 location, context, arg.get(), base, "labels_")) {
303 return labelExpr;
304 }
305 } else if (fname == "valueE") {
[bbf2cb1]306 if (auto valueExpr = resolveAttributeFunctions(
[0522ebe]307 location, context, arg.get(), base, "values_")) {
308 return valueExpr;
309 }
310 } else { // it is position; replace itself
311 return std::move(arg.get());
[544deb9]312 }
[0522ebe]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") {
[bbf2cb1]318 if (auto labelExpr = resolveAttributeFunctions(
[0522ebe]319 location, context, arg.get(), base, "labels_")) {
320 return labelExpr;
321 }
322 } else if (fname == "valueE") {
[bbf2cb1]323 if (auto valueExpr = resolveAttributeFunctions(
[0522ebe]324 location, context, arg.get(), base, "values_")) {
325 return valueExpr;
326 }
327 } else { // it is position; replace itself
328 return std::move(arg.get());
[ac939461]329 }
[0522ebe]330 } else {
331 SemanticError(argAsVar,
332 "Pseudo Enum Expression can only be used on an "
333 "enumeration instance");
[ac939461]334 }
335 }
336 return expr;
337}
338
[0522ebe]339ast::ptr<ast::Expr> reduceCastExpr(ast::ptr<ast::Expr> expr) {
340 if (auto castExpr = expr.as<ast::CastExpr>()) {
341 return reduceCastExpr(castExpr->arg);
342 }
343 return expr;
344}
345
[bbf2cb1]346struct ReplaceSuccAndPred final : public ast::WithSymbolTable,
347 public ast::WithConstTranslationUnit {
348 const ast::Expr* postvisit(const ast::ApplicationExpr* expr) {
349 auto fname = ast::getFunctionName(expr);
350 if (fname == "succ" || fname == "pred") {
351 const CodeLocation& location = expr->location;
352 if (expr->args.size() != 1) return expr;
353
354 auto param = expr->args.front();
355 if (auto argAsVar = reduceCastExpr(param).as<ast::VariableExpr>()) {
356 if (auto argAsDecl = argAsVar->var.as<ast::ObjectDecl>()) {
357 if (auto enumInst =
358 argAsDecl->type.as<ast::EnumInstType>()) {
359 auto castTo = new ast::EnumPosType(enumInst);
360 auto castExpr =
361 new ast::CastExpr(param->location, param, castTo);
362
363 auto untyped = new ast::UntypedExpr(
364 expr->location,
365 new ast::NameExpr(location, fname == "succ"
366 ? "_successor_"
367 : "_predessor_"),
368 {castExpr});
369 ResolvExpr::ResolveContext context{symtab,
370 transUnit().global};
371 auto typedResult =
372 ResolvExpr::findVoidExpression(untyped, context);
373 ast::ptr<ast::ApplicationExpr> ret =
374 typedResult.strict_as<ast::ApplicationExpr>();
375 return ast::deepCopy(ret);
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);
415 }
416 }
417 }
418 }
419 return expr;
[0522ebe]420 }
421};
422
[544deb9]423} // namespace
[ac939461]424
[544deb9]425void replacePseudoFunc(ast::TranslationUnit& translationUnit) {
[c75b30a]426 ast::Pass<WrapEnumValueExpr>::run(translationUnit);
[544deb9]427 ast::Pass<FindGenEnumArray>::run(translationUnit);
[bbf2cb1]428
[544deb9]429 ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit);
430 ast::Pass<ReplacePseudoFuncCore>::run(translationUnit);
[bbf2cb1]431
432 ast::Pass<ReplaceSuccAndPred>::run(translationUnit);
[ac939461]433}
[544deb9]434} // namespace Validate
Note: See TracBrowser for help on using the repository browser.