Changeset af746cc for src/Validate
- Timestamp:
- Apr 15, 2024, 12:03:53 PM (5 weeks ago)
- Branches:
- master
- Children:
- dc58e5d
- Parents:
- d9bad51
- Location:
- src/Validate
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Validate/Autogen.cpp
rd9bad51 raf746cc 196 196 197 197 bool shouldAutogen() const final { return true; } 198 void genAttrFuncForward();199 void genPosFunctions();200 198 private: 201 199 void genFuncBody( ast::FunctionDecl * decl ) final; 202 200 void genFieldCtors() final; 203 201 const ast::Decl * getDecl() const final { return decl; } 204 205 ast::FunctionDecl * genPosProto() const;206 ast::FunctionDecl * genLabelProto() const;207 ast::FunctionDecl * genValueProto() const;208 ast::FunctionDecl * genSuccProto() const;209 ast::FunctionDecl * genPredProto() const;210 211 ast::FunctionDecl * genSuccPosProto() const;212 ast::FunctionDecl * genPredPosProto() const;213 214 ast::FunctionDecl * genSuccPredFunc( bool succ );215 // ast::FunctionDecl * genPredFunc();216 202 }; 217 203 … … 256 242 enumInst.base = enumDecl; 257 243 EnumFuncGenerator gen( enumDecl, &enumInst, functionNesting ); 258 if ( enumDecl->base ) {259 gen.genAttrFuncForward();260 gen.genPosFunctions();261 }262 244 gen.generateAndAppendFunctions( declsToAddAfter ); 263 245 } … … 418 400 } 419 401 420 /// Use the current type T to create `void ?{}(T & _dst)`.402 /// Use the current type T to create `void ^?{}(T & _dst)`. 421 403 ast::FunctionDecl * FuncGenerator::genDtorProto() const { 422 404 // The destructor must be mutex on a concurrent type. … … 777 759 } 778 760 779 ast::FunctionDecl * EnumFuncGenerator::genPosProto() const {780 return genProto( "posE",781 { new ast::ObjectDecl( getLocation(), "_i",782 new ast::EnumInstType( decl ) )},783 { new ast::ObjectDecl( getLocation(), "_ret",784 new ast::BasicType{ ast::BasicType::UnsignedInt } )} );785 }786 787 ast::FunctionDecl * EnumFuncGenerator::genLabelProto() const {788 return genProto( "labelE",789 { new ast::ObjectDecl( getLocation(), "_i",790 new ast::EnumInstType( decl ) ) },791 { new ast::ObjectDecl( getLocation(), "_ret",792 new ast::PointerType( new ast::BasicType{ ast::BasicType::Char } ) ) } );793 }794 795 ast::FunctionDecl * EnumFuncGenerator::genValueProto() const {796 return genProto( "valueE",797 { new ast::ObjectDecl( getLocation(), "_i", new ast::EnumInstType( decl ) )},798 { new ast::ObjectDecl( getLocation(), "_ret", ast::deepCopy( decl->base ) ) } );799 }800 801 ast::FunctionDecl * EnumFuncGenerator::genSuccProto() const {802 return genProto( "succ",803 { new ast::ObjectDecl( getLocation(), "_i", new ast::EnumInstType( decl ) )},804 { new ast::ObjectDecl( getLocation(), "_ret", new ast::EnumInstType( decl ))} );805 }806 807 ast::FunctionDecl * EnumFuncGenerator::genPredProto() const {808 return genProto( "pred",809 { new ast::ObjectDecl( getLocation(), "_i", new ast::EnumInstType( decl ))},810 { new ast::ObjectDecl( getLocation(), "_ret", new ast::EnumInstType( decl ))} );811 }812 813 ast::FunctionDecl * EnumFuncGenerator::genSuccPosProto() const {814 return genProto( "_successor_",815 { new ast::ObjectDecl( getLocation(), "_i",816 new ast::EnumPosType( new ast::EnumInstType( decl ) ) )},817 {818 new ast::ObjectDecl( getLocation(), "_ret",819 new ast::EnumPosType( new ast::EnumInstType( decl ) ) )820 } );821 }822 823 ast::FunctionDecl * EnumFuncGenerator::genPredPosProto() const {824 return genProto( "_predessor_",825 { new ast::ObjectDecl( getLocation(), "_i",826 new ast::EnumPosType( new ast::EnumInstType( decl ) ) )},827 {828 new ast::ObjectDecl( getLocation(), "_ret",829 new ast::EnumPosType( new ast::EnumInstType( decl ) ) )830 } );831 }832 833 ast::FunctionDecl * EnumFuncGenerator::genSuccPredFunc( bool succ ) {834 ast::FunctionDecl * decl = succ? genSuccPosProto(): genPredPosProto();835 produceForwardDecl( decl );836 837 const CodeLocation& location = getLocation();838 839 auto & params = decl->params;840 assert( params.size() == 1 );841 auto param = params.front().strict_as<ast::ObjectDecl>();842 843 auto newReturn = new ast::ObjectDecl( location, "_returns",844 new ast::BasicType{ ast::BasicType::SignedInt} );845 846 847 ast::UntypedExpr * addOneExpr = new ast::UntypedExpr( location,848 new ast::NameExpr( location, succ? "?+?": "?-?" )849 );850 addOneExpr->args.push_back(851 new ast::CastExpr( location,852 new ast::VariableExpr( location, param ),853 new ast::BasicType{ ast::BasicType::SignedInt }854 )855 );856 addOneExpr->args.push_back(857 ast::ConstantExpr::from_int( location, 1 )858 );859 860 ast::UntypedExpr * assignExpr = new ast::UntypedExpr( location,861 new ast::NameExpr( location, "?=?" )862 );863 assignExpr->args.push_back(864 new ast::VariableExpr( location, newReturn )865 );866 assignExpr->args.push_back(867 addOneExpr868 );869 870 decl->stmts = new ast::CompoundStmt( location,871 {872 new ast::DeclStmt( location, newReturn ),873 new ast::ExprStmt( location, assignExpr ),874 new ast::ReturnStmt( location,875 new ast::VariableExpr( location, newReturn ))876 } );877 878 return decl;879 }880 881 void EnumFuncGenerator::genAttrFuncForward() {882 if ( decl->base ) {883 ast::FunctionDecl *(EnumFuncGenerator::*attrProtos[5])() const = {884 &EnumFuncGenerator::genPosProto, &EnumFuncGenerator::genLabelProto,885 &EnumFuncGenerator::genValueProto, &EnumFuncGenerator::genSuccProto,886 &EnumFuncGenerator::genPredProto887 // ,&EnumFuncGenerator::genSuccPosProto,888 // &EnumFuncGenerator::genPredPosProto889 };890 for ( auto & generator : attrProtos ) {891 produceForwardDecl( (this->*generator)() );892 }893 }894 }895 896 void EnumFuncGenerator::genPosFunctions() {897 if ( decl->base ) {898 ast::FunctionDecl * succ = genSuccPredFunc( true );899 ast::FunctionDecl * pred = genSuccPredFunc( false );900 produceDecl( succ );901 produceDecl( pred );902 }903 904 }905 906 761 void TypeFuncGenerator::genFieldCtors() { 907 762 // Opaque types do not have field constructors. -
src/Validate/ReplacePseudoFunc.cpp
rd9bad51 raf746cc 16 16 17 17 namespace { 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 now155 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 arrary234 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 resolution238 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 constant286 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 itself311 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 itself328 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 18 339 19 ast::ptr<ast::Expr> reduceCastExpr(ast::ptr<ast::Expr> expr) { … … 357 37 if (auto enumInst = 358 38 argAsDecl->type.as<ast::EnumInstType>()) { 359 auto castTo = new ast::EnumPosType(enumInst); 39 auto castTo = new ast::EnumAttrType( 40 enumInst, ast::EnumAttribute::Posn); 360 41 auto castExpr = 361 42 new ast::CastExpr(param->location, param, castTo); … … 375 56 return ast::deepCopy(ret); 376 57 } 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); 58 argAsDecl->type.as<ast::EnumAttrType>()) { 59 std::cerr << "PseudoFunc: succ/pred should not be applied on EnumAttrType directly" << std::endl; 415 60 } 416 61 } … … 424 69 425 70 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 432 71 ast::Pass<ReplaceSuccAndPred>::run(translationUnit); 433 72 } -
src/Validate/module.mk
rd9bad51 raf746cc 54 54 Validate/VerifyCtorDtorAssign.hpp \ 55 55 Validate/ReplacePseudoFunc.cpp \ 56 Validate/ReplacePseudoFunc.hpp 56 Validate/ReplacePseudoFunc.hpp \ 57 Validate/ImplementEnumFunc.cpp \ 58 Validate/ImplementEnumFunc.hpp 57 59 58 60 SRCDEMANGLE += $(SRC_VALIDATE)
Note: See TracChangeset
for help on using the changeset viewer.