- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Validate/ReplacePseudoFunc.cpp
r544deb9 rac939461 1 #include "AST/Decl.hpp" 2 #include "AST/Pass.hpp" 3 #include "AST/Stmt.hpp" 4 #include "AST/Inspect.hpp" 5 #include "Common/utility.h" 1 6 #include "ReplacePseudoFunc.hpp" 2 7 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 Mangler12 8 namespace Validate { 13 9 14 10 namespace { 15 11 16 std::set<std::string> queryLabels; 17 std::set<std::string> queryValues; 18 19 struct FindGenEnumArray final : public ast::WithShortCircuiting { 20 void previsit(const ast::ApplicationExpr* enumDecl); 12 struct ReplacePseudoFuncCore { 13 ast::Expr const * postvisit( ast::ApplicationExpr const * decl ); 21 14 }; 22 23 void 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 15 } 49 16 50 struct PseudoFuncGenerateRoutine final : public ast::WithDeclsToAdd<>, 51 public ast::WithSymbolTable, 52 public ast::WithShortCircuiting { 53 void previsit(const ast::EnumDecl* enumDecl); 54 }; 55 56 void 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 97 struct ReplacePseudoFuncCore : public ast::WithShortCircuiting, 98 public ast::WithSymbolTable, 99 public ast::WithConstTranslationUnit { 100 ast::Expr const* postvisit(ast::ApplicationExpr const* decl); 101 }; 102 103 ast::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"); 17 ast::Expr const * ReplacePseudoFuncCore::postvisit( ast::ApplicationExpr const * expr) { 18 auto fname = ast::getFunctionName( expr ); 19 if ( fname == "posE" ) { 20 // std::cerr << "Found App in ReplacePseudoFunc" << std::endl; 21 if ( expr->args.size() != 1 ) { 22 SemanticError( expr, "Position Expression only take one parameter" ); 111 23 } 112 ast::ptr<ast::VariableExpr> arg = 113 expr->args.front().as<const ast::VariableExpr>(); 114 if (!arg) { 115 SemanticError(expr, "Unimplement Pseudo Function Cases"); 24 const ast::VariableExpr * arg = expr->args.front().as<const ast::VariableExpr>(); 25 if ( !arg ) { 26 SemanticError( expr, "Unimplement Pseudo Function Cases" ); 116 27 } 117 const ast::ObjectDecl * argAsVar = arg->var.as<const ast::ObjectDecl>();28 const ast::ObjectDecl * argAsVar = arg->var.as<const ast::ObjectDecl>(); 118 29 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"); 30 const ast::EnumInstType * argType = argAsVar->type.as<const ast::EnumInstType>(); 31 if ( !argType ) { 32 SemanticError( argAsVar, "Position can only be used on an enumeration instance" ); 125 33 } 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 } 34 const ast::EnumDecl * base = argType->base; 35 for ( size_t i = 0; i < base->members.size(); i++ ) { 36 if ( base->members[i]->name == referredName ) { 37 return ast::ConstantExpr::from_int( expr->location, i ); 186 38 } 187 39 } … … 190 42 } 191 43 192 } // namespace193 44 194 void replacePseudoFunc(ast::TranslationUnit& translationUnit) { 195 ast::Pass<FindGenEnumArray>::run(translationUnit); 196 ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit); 197 ast::Pass<ReplacePseudoFuncCore>::run(translationUnit); 45 46 void replacePseudoFunc( ast::TranslationUnit & translationUnit ) { 47 ast::Pass<ReplacePseudoFuncCore>::run( translationUnit ); 198 48 } 199 } // namespace Validate 49 50 }
Note: See TracChangeset
for help on using the changeset viewer.