source: src/Validate/ReplacePseudoFunc.cpp@ 77bc259

Last change on this file since 77bc259 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
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"
12
13#include "AST/Print.hpp"
14
15#include "ResolvExpr/CandidateFinder.hpp"
16
17namespace Validate {
18
19namespace {
20
21std::set<std::string> queryLabels;
22std::set<std::string> queryValues;
23
24// struct AutoInit {
25// ast::EnumDecl const* postvisit( const ast::EnumDecl* expr );
26// };
27
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);
34 void previsit(const ast::VariableExpr* ) { visit_children = false; }
35
36 ast::Expr const* postvisit(const ast::VariableExpr* expr);
37};
38
39struct FindGenEnumArray final : public ast::WithShortCircuiting {
40 void previsit(const ast::ApplicationExpr* enumDecl);
41};
42
43struct PseudoFuncGenerateRoutine final : public ast::WithDeclsToAdd<>,
44 public ast::WithSymbolTable,
45 public ast::WithShortCircuiting,
46 public ast::WithConstTranslationUnit {
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
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// }
64
65void WrapEnumValueExpr::previsit(const ast::ApplicationExpr* expr) {
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
73 if (fname == "labelE" || fname == "valueE" || fname == "posE") {
74 visit_children = false;
75 }
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"),
96 { std::move( expr ) });
97 ResolvExpr::ResolveContext context{symtab, transUnit().global};
98 auto result = ResolvExpr::findVoidExpression(untyped, context);
99 ast::ptr<ast::ApplicationExpr> ret =
100 result.strict_as<ast::ApplicationExpr>();
101 return ast::deepCopy( ret );
102 }
103 }
104 return expr;
105}
106
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 }
132}
133
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
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;
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 }
188 labels.emplace_back(new ast::SingleInit(
189 location, ast::ConstantExpr::from_string(location, mem->name)));
190 }
191 if (queryValues.count(enumDecl->name)) {
192 auto init = new ast::ListInit(location, std::move(inits));
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);
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));
206 auto labels = new ast::ObjectDecl(
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);
213 symtab.addId(labels);
214 labels->mangleName = Mangle::mangle(labels);
215 declsToAddAfter.push_back(labels);
216 }
217}
218
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, "?[?]"),
228 { std::move(arrAsVar), std::move(arg) });
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}
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");
244 }
245 ast::ptr<ast::VariableExpr> arg =
246 expr->args.front().as<const ast::VariableExpr>();
247 if (!arg) {
248 SemanticError(expr, "Unimplement Pseudo Function Cases");
249 }
250 const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();
251 const std::string referredName = argAsVar->name;
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;
260 ResolvExpr::ResolveContext context{symtab, transUnit().global};
261 // If resolvable as constant
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);
269 else {
270 return getPseudoFuncApplication(location, context, arg.get(),
271 base, "values_");
272 }
273
274 }
275 }
276
277 if (fname == "labelE") {
278 if (auto labelExpr =
279 getPseudoFuncApplication(location, context, arg.get(), base, "labels_")) {
280 return labelExpr;
281 }
282 } else if (fname == "valueE") {
283 if (auto valueExpr =
284 getPseudoFuncApplication(location, context, arg.get(), base, "values_")) {
285 return valueExpr;
286 }
287 } else { // it is position; replace itself
288 return std::move( arg.get() );
289 }
290 }
291 return expr;
292}
293
294} // namespace
295
296void replacePseudoFunc(ast::TranslationUnit& translationUnit) {
297 ast::Pass<WrapEnumValueExpr>::run(translationUnit);
298 ast::Pass<FindGenEnumArray>::run(translationUnit);
299 ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit);
300 ast::Pass<ReplacePseudoFuncCore>::run(translationUnit);
301}
302} // namespace Validate
Note: See TracBrowser for help on using the repository browser.