source: src/Validate/ReplacePseudoFunc.cpp@ a22d148

Last change on this file since a22d148 was a55ebcc, checked in by JiadaL <j82liang@…>, 20 months ago
  1. Add debug print option for replacePseudoFunc; 2. Change resolver handling enum types; 3. change QualifiedNameExpr representation pre-resolver; 4. Disable able a test that currently doesn't work
  • Property mode set to 100644
File size: 11.6 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"
8#include "AST/Stmt.hpp"
9#include "Common/utility.h"
[544deb9]10#include "ResolvExpr/Resolver.h"
[a55ebcc]11#include "SymTab/Mangler.h"
12
13#include "AST/Print.hpp"
14
15#include "ResolvExpr/CandidateFinder.hpp"
16
[ac939461]17namespace Validate {
18
19namespace {
20
[544deb9]21std::set<std::string> queryLabels;
22std::set<std::string> queryValues;
23
[a55ebcc]24// struct AutoInit {
25// ast::EnumDecl const* postvisit( const ast::EnumDecl* expr );
26// };
27
[c75b30a]28struct WrapEnumValueExpr final : public ast::WithShortCircuiting,
29 public ast::WithSymbolTable,
30 public ast::WithConstTranslationUnit {
31 void previsit(const ast::DeclStmt* expr);
32 void previsit(const ast::ApplicationExpr* expr);
33 void previsit(const ast::CastExpr* expr);
[a55ebcc]34 void previsit(const ast::VariableExpr* ) { visit_children = false; }
[c75b30a]35
36 ast::Expr const* postvisit(const ast::VariableExpr* expr);
37};
38
[544deb9]39struct FindGenEnumArray final : public ast::WithShortCircuiting {
40 void previsit(const ast::ApplicationExpr* enumDecl);
[ac939461]41};
[544deb9]42
[c75b30a]43struct PseudoFuncGenerateRoutine final : public ast::WithDeclsToAdd<>,
44 public ast::WithSymbolTable,
[a55ebcc]45 public ast::WithShortCircuiting,
46 public ast::WithConstTranslationUnit {
[c75b30a]47 void previsit(const ast::EnumDecl* enumDecl);
48};
49
50struct ReplacePseudoFuncCore : public ast::WithShortCircuiting,
51 public ast::WithSymbolTable,
52 public ast::WithConstTranslationUnit {
53 ast::Expr const* postvisit(ast::ApplicationExpr const* decl);
54};
55
[a55ebcc]56// ast::EnumDecl const * AutoInit::postvisit( const ast::EnumDecl * expr ) {
57// for ( size_t i = 0; i < expr->members.size(); i++ ) {
58// auto mem = expr->members[i].as<ast::ObjectDecl>();
59// assert( mem );
60// if ( mem->init )
61// }
62// return expr;
63// }
[c75b30a]64
[a55ebcc]65void WrapEnumValueExpr::previsit(const ast::ApplicationExpr* expr) {
[c75b30a]66 auto varExpr = expr->func.as<ast::VariableExpr>();
67 auto fname = ast::getFunctionName(expr);
68 if ( !varExpr || varExpr->var->linkage == ast::Linkage::Intrinsic ) {
69 if ( fname == "?{}" || fname == "?=?" )
70 visit_children = false;
71 }
72
[a55ebcc]73 if (fname == "labelE" || fname == "valueE" || fname == "posE") {
[c75b30a]74 visit_children = false;
[a55ebcc]75 }
[c75b30a]76}
77
78void WrapEnumValueExpr::previsit(const ast::DeclStmt*) {
79 visit_children = false;
80}
81
82void WrapEnumValueExpr::previsit(const ast::CastExpr* expr) {
83 if (expr->result && expr->result.as<ast::ReferenceType>()) {
84 visit_children = false;
85 }
86}
87
88ast::Expr const* WrapEnumValueExpr::postvisit(const ast::VariableExpr* expr) {
89 if (!expr->result) {
90 return expr;
91 }
92 if (auto enumInst = expr->result.as<ast::EnumInstType>()) {
93 if (enumInst->base && enumInst->base->base) {
94 auto untyped = new ast::UntypedExpr(
95 expr->location, new ast::NameExpr(expr->location, "valueE"),
[a55ebcc]96 { std::move( expr ) });
[c75b30a]97 ResolvExpr::ResolveContext context{symtab, transUnit().global};
98 auto result = ResolvExpr::findVoidExpression(untyped, context);
[a55ebcc]99 ast::ptr<ast::ApplicationExpr> ret =
[c75b30a]100 result.strict_as<ast::ApplicationExpr>();
[a55ebcc]101 return ast::deepCopy( ret );
[c75b30a]102 }
103 }
104 return expr;
105}
106
[544deb9]107void FindGenEnumArray::previsit(const ast::ApplicationExpr* expr) {
108 auto fname = ast::getFunctionName(expr);
109 if (fname == "labelE" || fname == "valueE") {
110 if (expr->args.size() != 1) {
111 SemanticError(expr, "Position Expression only take one parameter");
112 }
113 const ast::VariableExpr* arg =
114 expr->args.front().as<const ast::VariableExpr>();
115 if (!arg) {
116 SemanticError(expr, "Unimplement Pseudo Function Cases");
117 }
118 const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();
119 const std::string referredName = argAsVar->name;
120 const ast::EnumInstType* argType =
121 argAsVar->type.as<const ast::EnumInstType>();
122 if (!argType) {
123 SemanticError(
124 argAsVar,
125 "Position can only be used on an enumeration instance");
126 }
127 ast::ptr<ast::EnumDecl> base = argType->base;
128 assert(base);
129 if (fname == "labelE") queryLabels.insert(base->name);
130 if (fname == "valueE") queryValues.insert(base->name);
131 }
[ac939461]132}
133
[a55ebcc]134const ast::Init * getAutoInit( const CodeLocation & location,
135 const ast::Type * type, ResolvExpr::ResolveContext context, const ast::Init * prev ) {
136 if ( auto prevInit = dynamic_cast< const ast::SingleInit * >( prev ) ) {
137 auto prevInitExpr = prevInit->value;
138 if ( auto constInit = prevInitExpr.as< ast::ConstantExpr >() ) {
139 // Assume no string literal for now
140 return new ast::SingleInit(
141 location,
142 ast::ConstantExpr::from_int(
143 location, constInit->intValue() + 1 )
144 );
145 } else {
146 auto untypedThisInit = new ast::UntypedExpr(
147 location,
148 new ast::NameExpr( location, "?++" ),
149 { prevInitExpr }
150 );
151 auto typedInit = ResolvExpr::findSingleExpression(untypedThisInit, type,
152 context );
153 return new ast::SingleInit( location, typedInit );
154 }
155 }
156 SemanticError( prev, "Auto Init a List is not implemented" );
157 return prev;
158}
159
[544deb9]160void PseudoFuncGenerateRoutine::previsit(const ast::EnumDecl* enumDecl) {
161 visit_children = false;
162 const CodeLocation& location = enumDecl->location;
163 if (enumDecl->members.size() == 0 || !enumDecl->base) return;
164
165 std::vector<ast::ptr<ast::Init>> inits;
166 std::vector<ast::ptr<ast::Init>> labels;
[a55ebcc]167 auto type = enumDecl->base;
168
169 for ( size_t i = 0; i < enumDecl->members.size(); i++ ) {
170 ast::ptr<ast::Decl> mem = enumDecl->members.at( i );
171 auto memAsObjectDecl = mem.as< ast::ObjectDecl >();
172 assert( memAsObjectDecl );
173 if ( memAsObjectDecl->init ) {
174 inits.emplace_back( memAsObjectDecl->init );
175 } else {
176 const CodeLocation & location = mem->location;
177 if ( i == 0 ) {
178 inits.emplace_back( new ast::SingleInit(
179 location,
180 ast::ConstantExpr::from_int( mem->location, 0 )
181 ) );
182 } else {
183 inits.emplace_back( getAutoInit( location, enumDecl->base,
184 ResolvExpr::ResolveContext{symtab, transUnit().global},
185 inits.at( i - 1 ).as<ast::SingleInit>()) );
186 }
187 }
[544deb9]188 labels.emplace_back(new ast::SingleInit(
[a55ebcc]189 location, ast::ConstantExpr::from_string(location, mem->name)));
190 }
[544deb9]191 if (queryValues.count(enumDecl->name)) {
192 auto init = new ast::ListInit(location, std::move(inits));
[c75b30a]193 const ast::ArrayType* arrT = new ast::ArrayType(
194 enumDecl->base,
195 ast::ConstantExpr::from_int(location, enumDecl->members.size()),
196 ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim);
197 ast::ObjectDecl* values = new ast::ObjectDecl(
198 location, "values_" + enumDecl->name, arrT, init,
199 ast::Storage::Static, ast::Linkage::AutoGen);
[544deb9]200 symtab.addId(values);
201 values->mangleName = Mangle::mangle(values);
202 declsToAddAfter.push_back(values);
203 }
204 if (queryLabels.count(enumDecl->name)) {
205 auto label_strings = new ast::ListInit(location, std::move(labels));
[c75b30a]206 auto labels = new ast::ObjectDecl(
[544deb9]207 location, "labels_" + enumDecl->name,
208 new ast::ArrayType(
209 new ast::PointerType(new ast::BasicType{ast::BasicType::Char}),
210 ast::ConstantExpr::from_int(location, enumDecl->members.size()),
211 ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim),
212 label_strings, ast::Storage::Static, ast::Linkage::AutoGen);
[c75b30a]213 symtab.addId(labels);
214 labels->mangleName = Mangle::mangle(labels);
215 declsToAddAfter.push_back(labels);
[544deb9]216 }
217}
218
[c75b30a]219ast::ApplicationExpr const* getPseudoFuncApplication(
220 const CodeLocation location, ResolvExpr::ResolveContext context,
221 const ast::VariableExpr* arg, const ast::EnumDecl* base, const std::string & name) {
222 ast::Expr* toResolve = new ast::NameExpr(location, name + base->name);
223 auto result = ResolvExpr::findVoidExpression(toResolve, context);
224 assert(result.get());
225 auto arrAsVar = result.strict_as<ast::VariableExpr>();
226 auto untyped = new ast::UntypedExpr(
227 location, new ast::NameExpr(location, "?[?]"),
[496ffc17]228 { std::move(arrAsVar), std::move(arg) });
[c75b30a]229 auto typedResult = ResolvExpr::findVoidExpression(untyped, context);
230
231 ast::ptr<ast::ApplicationExpr> ret =
232 typedResult.strict_as<ast::ApplicationExpr>();
233 return ast::deepCopy(ret);
234}
[544deb9]235
236ast::Expr const* ReplacePseudoFuncCore::postvisit(
237 ast::ApplicationExpr const* expr) {
238 auto fname = ast::getFunctionName(expr);
239 auto location = expr->location;
240 if (fname == "posE" || fname == "valueE" || fname == "labelE") {
241 if (expr->args.size() != 1) {
242 SemanticError(expr,
243 "Pseudo Enum Expression only take one parameter");
[ac939461]244 }
[544deb9]245 ast::ptr<ast::VariableExpr> arg =
246 expr->args.front().as<const ast::VariableExpr>();
247 if (!arg) {
248 SemanticError(expr, "Unimplement Pseudo Function Cases");
[ac939461]249 }
[544deb9]250 const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();
[ac939461]251 const std::string referredName = argAsVar->name;
[544deb9]252 const ast::EnumInstType* argType =
253 argAsVar->type.as<const ast::EnumInstType>();
254 if (!argType) {
255 SemanticError(argAsVar,
256 "Pseudo Enum Expression can only be used on an "
257 "enumeration instance");
258 }
259 const ast::EnumDecl* base = argType->base;
[c75b30a]260 ResolvExpr::ResolveContext context{symtab, transUnit().global};
261 // If resolvable as constant
[544deb9]262 for (size_t i = 0; i < base->members.size(); i++) {
263 if (base->members[i]->name == referredName) {
264 if (fname == "posE")
265 return ast::ConstantExpr::from_int(expr->location, i);
266 else if (fname == "labelE")
267 return ast::ConstantExpr::from_string(expr->location,
268 referredName);
[a55ebcc]269 else {
[c75b30a]270 return getPseudoFuncApplication(location, context, arg.get(),
[a55ebcc]271 base, "values_");
272 }
273
[544deb9]274 }
275 }
276
277 if (fname == "labelE") {
[c75b30a]278 if (auto labelExpr =
279 getPseudoFuncApplication(location, context, arg.get(), base, "labels_")) {
280 return labelExpr;
[544deb9]281 }
[c75b30a]282 } else if (fname == "valueE") {
283 if (auto valueExpr =
284 getPseudoFuncApplication(location, context, arg.get(), base, "values_")) {
285 return valueExpr;
[ac939461]286 }
[c75b30a]287 } else { // it is position; replace itself
288 return std::move( arg.get() );
[ac939461]289 }
290 }
291 return expr;
292}
293
[544deb9]294} // namespace
[ac939461]295
[544deb9]296void replacePseudoFunc(ast::TranslationUnit& translationUnit) {
[c75b30a]297 ast::Pass<WrapEnumValueExpr>::run(translationUnit);
[544deb9]298 ast::Pass<FindGenEnumArray>::run(translationUnit);
299 ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit);
300 ast::Pass<ReplacePseudoFuncCore>::run(translationUnit);
[ac939461]301}
[544deb9]302} // namespace Validate
Note: See TracBrowser for help on using the repository browser.