- File:
-
- 1 edited
-
src/Validate/ReplacePseudoFunc.cpp (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Validate/ReplacePseudoFunc.cpp
rfb2e916 r76fe046 17 17 namespace { 18 18 19 std::set<std::string> queryLabels; 20 std::set<std::string> queryValues; 21 22 struct 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 33 const inline std::string getValueArrayName(std::string enumName) { 34 return "values_" + enumName; 35 } 36 37 // struct AutoInit { 38 // ast::EnumDecl const* postvisit( const ast::EnumDecl* expr ); 39 // }; 40 41 struct 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); 47 void previsit(const ast::VariableExpr*) { visit_children = false; } 48 49 ast::Expr const* postvisit(const ast::VariableExpr* expr); 50 }; 51 52 struct FindGenEnumArray final : public ast::WithShortCircuiting { 53 void previsit(const ast::ApplicationExpr* enumDecl); 54 }; 55 56 struct PseudoFuncGenerateRoutine final : public ast::WithDeclsToAdd<>, 57 public ast::WithSymbolTable, 58 public ast::WithShortCircuiting, 59 public ast::WithConstTranslationUnit { 60 void previsit(const ast::EnumDecl* enumDecl); 61 }; 62 63 struct ReplacePseudoFuncCore : public ast::WithShortCircuiting, 64 public ast::WithSymbolTable, 65 public ast::WithConstTranslationUnit { 66 ast::Expr const* postvisit(ast::ApplicationExpr const* decl); 67 }; 68 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 // } 77 78 void WrapEnumValueExpr::previsit(const ast::ApplicationExpr* expr) { 79 auto varExpr = expr->func.as<ast::VariableExpr>(); 80 auto fname = ast::getFunctionName(expr); 81 if (!varExpr || varExpr->var->linkage == ast::Linkage::Intrinsic) { 82 if (fname == "?{}" || fname == "?=?") visit_children = false; 83 } 84 85 if (fname == "labelE" || fname == "valueE" || fname == "posE" || 86 fname == "pred" || fname == "succ") { 87 visit_children = false; 88 } 89 } 90 91 void WrapEnumValueExpr::previsit(const ast::DeclStmt*) { 92 visit_children = false; 93 } 94 95 void WrapEnumValueExpr::previsit(const ast::CastExpr* expr) { 96 if (expr->result && expr->result.as<ast::ReferenceType>()) { 97 visit_children = false; 98 } 99 } 100 101 ast::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"), 109 {std::move(expr)}); 110 ResolvExpr::ResolveContext context{symtab, transUnit().global}; 111 auto result = ResolvExpr::findVoidExpression(untyped, context); 112 ast::ptr<ast::ApplicationExpr> ret = 113 result.strict_as<ast::ApplicationExpr>(); 114 return ast::deepCopy(ret); 115 } 116 } 117 return expr; 118 } 119 120 void 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 } 145 } 146 147 const 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)) { 152 auto prevInitExpr = prevInit->value; 153 if (auto constInit = prevInitExpr.as<ast::ConstantExpr>()) { 154 // Assume no string literal for now 155 return new ast::SingleInit( 156 location, ast::ConstantExpr::from_int( 157 location, constInit->intValue() + 1)); 158 } else { 159 auto untypedThisInit = new ast::UntypedExpr( 160 location, new ast::NameExpr(location, "?++"), {prevInitExpr}); 161 auto typedInit = ResolvExpr::findSingleExpression(untypedThisInit, 162 type, context); 163 return new ast::SingleInit(location, typedInit); 164 } 165 } 166 SemanticError(prev, "Auto Init a List is not implemented"); 167 return prev; 168 } 169 170 void 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; 177 auto type = enumDecl->base; 178 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); 185 } else { 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))); 190 } else { 191 inits.emplace_back(getAutoInit( 192 location, enumDecl->base, 193 ResolvExpr::ResolveContext{symtab, transUnit().global}, 194 inits.at(i - 1).as<ast::SingleInit>())); 195 } 196 } 197 labels.emplace_back(new ast::SingleInit( 198 location, ast::ConstantExpr::from_string(location, mem->name))); 199 } 200 if (queryValues.count(enumDecl->name)) { 201 auto init = new ast::ListInit(location, std::move(inits)); 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); 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)); 215 auto labels = new ast::ObjectDecl( 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); 222 symtab.addId(labels); 223 labels->mangleName = Mangle::mangle(labels); 224 declsToAddAfter.push_back(labels); 225 } 226 } 227 228 ast::ApplicationExpr const* resolveAttributeFunctions( 229 const CodeLocation location, ResolvExpr::ResolveContext context, 230 const ast::VariableExpr* arg, const ast::EnumDecl* base, 231 const std::string& name) { 232 ast::Expr* toResolve = new ast::NameExpr(location, name + base->name); 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); 243 mutatedArg = ast::mutate_field(mutatedArg, &ast::VariableExpr::result, 244 mutatedArg->var->get_type()); 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 } 262 } 263 264 ast::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"); 272 } 273 ast::ptr<ast::VariableExpr> arg = 274 expr->args.front().as<const ast::VariableExpr>(); 275 if (!arg) { 276 SemanticError(expr, "Unimplement Pseudo Function Cases"); 277 } 278 const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>(); 279 const std::string referredName = argAsVar->name; 280 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 { 294 return resolveAttributeFunctions( 295 location, context, arg.get(), base, "values_"); 296 } 297 } 298 } 299 300 if (fname == "labelE") { 301 if (auto labelExpr = resolveAttributeFunctions( 302 location, context, arg.get(), base, "labels_")) { 303 return labelExpr; 304 } 305 } else if (fname == "valueE") { 306 if (auto valueExpr = resolveAttributeFunctions( 307 location, context, arg.get(), base, "values_")) { 308 return valueExpr; 309 } 310 } else { // it is position; replace itself 311 return std::move(arg.get()); 312 } 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") { 318 if (auto labelExpr = resolveAttributeFunctions( 319 location, context, arg.get(), base, "labels_")) { 320 return labelExpr; 321 } 322 } else if (fname == "valueE") { 323 if (auto valueExpr = resolveAttributeFunctions( 324 location, context, arg.get(), base, "values_")) { 325 return valueExpr; 326 } 327 } else { // it is position; replace itself 328 return std::move(arg.get()); 329 } 330 } else { 331 SemanticError(argAsVar, 332 "Pseudo Enum Expression can only be used on an " 333 "enumeration instance"); 334 } 335 } 336 return expr; 337 } 338 19 339 ast::ptr<ast::Expr> reduceCastExpr(ast::ptr<ast::Expr> expr) { 20 340 if (auto castExpr = expr.as<ast::CastExpr>()) { … … 37 357 if (auto enumInst = 38 358 argAsDecl->type.as<ast::EnumInstType>()) { 39 auto castTo = new ast::EnumAttrType( 40 enumInst, ast::EnumAttribute::Posn); 359 auto castTo = new ast::EnumPosType(enumInst); 41 360 auto castExpr = 42 361 new ast::CastExpr(param->location, param, castTo); … … 55 374 typedResult.strict_as<ast::ApplicationExpr>(); 56 375 return ast::deepCopy(ret); 57 } else if (argAsDecl->type.as<ast::EnumAttrType>()) { 58 std::cerr << "PseudoFunc: succ/pred should not be applied on EnumAttrType directly" << std::endl; 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); 59 415 } 60 416 } … … 68 424 69 425 void replacePseudoFunc(ast::TranslationUnit& translationUnit) { 426 ast::Pass<WrapEnumValueExpr>::run(translationUnit); 427 ast::Pass<FindGenEnumArray>::run(translationUnit); 428 429 ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit); 430 ast::Pass<ReplacePseudoFuncCore>::run(translationUnit); 431 70 432 ast::Pass<ReplaceSuccAndPred>::run(translationUnit); 71 433 }
Note:
See TracChangeset
for help on using the changeset viewer.