Changeset 0522ebe
- Timestamp:
- Feb 26, 2024, 3:49:23 AM (2 months ago)
- Branches:
- master
- Children:
- a4da45e
- Parents:
- c17dc80
- Location:
- src
- Files:
-
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Fwd.hpp
rc17dc80 r0522ebe 133 133 class OneType; 134 134 class GlobalScopeType; 135 class EnumPosType; 135 136 136 137 class Designation; -
src/AST/Pass.hpp
rc17dc80 r0522ebe 222 222 const ast::Type * visit( const ast::UnionInstType * ) override final; 223 223 const ast::Type * visit( const ast::EnumInstType * ) override final; 224 const ast::Type * visit( const ast::EnumPosType * ) override final; 224 225 const ast::Type * visit( const ast::TraitInstType * ) override final; 225 226 const ast::Type * visit( const ast::TypeInstType * ) override final; -
src/AST/Pass.impl.hpp
rc17dc80 r0522ebe 1986 1986 1987 1987 //-------------------------------------------------------------------------- 1988 // EnumPosType 1989 template< typename core_t > 1990 const ast::Type * ast::Pass< core_t >::visit( const ast::EnumPosType * node ) { 1991 VISIT_START( node ); 1992 1993 VISIT_END( Type, node ); 1994 } 1995 1996 //-------------------------------------------------------------------------- 1988 1997 // TraitInstType 1989 1998 template< typename core_t > -
src/AST/Print.cpp
rc17dc80 r0522ebe 1576 1576 } 1577 1577 1578 virtual const ast::Type * visit( const ast::EnumPosType * node ) override final { 1579 preprint( node ); 1580 os << "enum pos with "; 1581 (*(node->instance)).accept( *this ); 1582 return node; 1583 } 1584 1578 1585 virtual const ast::Type * visit( const ast::TraitInstType * node ) override final { 1579 1586 preprint( node ); -
src/AST/Type.hpp
rc17dc80 r0522ebe 362 362 using EnumInstType = SueInstType<EnumDecl>; 363 363 364 class EnumPosType final : public Type { 365 public: 366 readonly<EnumInstType> instance; 367 const Type * accept( Visitor & v ) const override { return v.visit( this ); } 368 EnumPosType( const EnumInstType * instance ): instance(instance) {} 369 370 private: 371 EnumPosType * clone() const override { return new EnumPosType{ *this }; } 372 MUTATE_FRIEND 373 }; 374 364 375 /// An instance of a trait type. 365 376 class TraitInstType final : public BaseInstType { -
src/AST/Visitor.hpp
rc17dc80 r0522ebe 119 119 virtual const ast::Type * visit( const ast::OneType * ) = 0; 120 120 virtual const ast::Type * visit( const ast::GlobalScopeType * ) = 0; 121 virtual const ast::Type * visit( const ast::EnumPosType * ) = 0; 121 122 virtual const ast::Designation * visit( const ast::Designation * ) = 0; 122 123 virtual const ast::Init * visit( const ast::SingleInit * ) = 0; -
src/CodeGen/GenType.cc
rc17dc80 r0522ebe 46 46 void postvisit( ast::UnionInstType const * type ); 47 47 void postvisit( ast::EnumInstType const * type ); 48 void postvisit( ast::EnumPosType const * type ); 48 49 void postvisit( ast::TypeInstType const * type ); 49 50 void postvisit( ast::TupleType const * type ); … … 239 240 } 240 241 242 void GenType::postvisit( ast::EnumPosType const * type ) { 243 postvisit( type->instance ); 244 } 245 241 246 void GenType::postvisit( ast::TypeInstType const * type ) { 242 247 assertf( !options.genC, "TypeInstType should not reach code generation." ); -
src/Common/CodeLocationTools.cpp
rc17dc80 r0522ebe 188 188 macro(UnionInstType, Type) \ 189 189 macro(EnumInstType, Type) \ 190 macro(EnumPosType, Type) \ 190 191 macro(TraitInstType, Type) \ 191 192 macro(TypeInstType, Type) \ -
src/Parser/parser.yy
rc17dc80 r0522ebe 3006 3006 | assertion_list 3007 3007 { $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); } 3008 | ENUM '(' identifier_or_type_name ')' identifier_or_type_name new_type_class type_initializer_opt assertion_list_opt 3009 { 3010 typedefTable.addToScope( *$3, TYPEDIMname, "type_parameter 4" ); 3011 typedefTable.addToScope( *$5, TYPEDIMname, "type_parameter 5" ); 3012 $$ = DeclarationNode::newTypeParam( $6, $5 )->addTypeInitializer( $7 )->addAssertions( $8 ); 3013 } 3008 3014 ; 3009 3015 -
src/ResolvExpr/CandidateFinder.cpp
rc17dc80 r0522ebe 893 893 } 894 894 else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) { 895 // The Attribute Arrays are not yet generated, need to proxy them 896 // as attribute function call 897 const CodeLocation & location = cand->expr->location; 898 if ( enumInst->base && enumInst->base->base ) { 899 auto valueName = new ast::NameExpr(location, "valueE"); 900 auto untypedValueCall = new ast::UntypedExpr( 901 location, valueName, { aggrExpr } ); 902 auto result = ResolvExpr::findVoidExpression( untypedValueCall, context ); 903 assert( result.get() ); 904 CandidateRef newCand = std::make_shared<Candidate>( 905 *cand, result, Cost::safe ); 906 candidates.emplace_back( std::move( newCand ) ); 907 } 895 if (enumInst->base && enumInst->base->base) { 896 const CodeLocation &location = cand->expr->location; 897 898 CandidateFinder funcFinder(context, tenv); 899 auto nameExpr = new ast::NameExpr(location, "valueE"); 900 ResolveMode mode = {true, false, selfFinder.candidates.empty()}; 901 funcFinder.find( nameExpr, mode ); 902 903 // make variableExpr itself the candidate for the value Call 904 ExplodedArgs argExpansions; 905 argExpansions.emplace_back(); 906 auto &argE = argExpansions.back(); 907 908 argE.emplace_back(*cand, symtab); // Use the typed name expr as param for value 909 910 CandidateList found; 911 SemanticErrorException errors; 912 913 for (CandidateRef &func : funcFinder) { 914 try { 915 const ast::Type *funcResult = 916 func->expr->result->stripReferences(); 917 if (auto pointer = dynamic_cast<const ast::PointerType *>( 918 funcResult)) { 919 if (auto function = 920 pointer->base.as<ast::FunctionType>()) { 921 CandidateRef newFunc{new Candidate{*func}}; 922 newFunc->expr = referenceToRvalueConversion( 923 newFunc->expr, newFunc->cost); 924 makeFunctionCandidates( location, 925 newFunc, function, 926 argExpansions, found ); 927 } 928 } 929 } catch (SemanticErrorException &e) { 930 std::cerr 931 << "Resolving value function should cause an error" 932 << std::endl; 933 errors.append(e); 934 } 935 } 936 937 if (found.empty()) { 938 std::cerr << "Resolve value function should always success" 939 << std::endl; 940 } 941 942 for (CandidateRef &withFunc : found) { 943 withFunc->cost.incSafe(); 944 Cost cvtCost = 945 computeApplicationConversionCost(withFunc, symtab); 946 assert(cvtCost != Cost::infinity); 947 948 candidates.emplace_back(std::move(withFunc)); 949 } 950 } 908 951 } 909 952 } … … 1401 1444 } 1402 1445 1403 void Finder::postvisit( const ast::VariableExpr * variableExpr ) { 1404 // not sufficient to just pass `variableExpr` here, type might have changed since 1405 addCandidate( variableExpr, tenv ); 1406 } 1446 void Finder::postvisit(const ast::VariableExpr *variableExpr) { 1447 // not sufficient to just pass `variableExpr` here, type might have changed 1448 1449 auto cand = new Candidate(variableExpr, tenv); 1450 candidates.emplace_back(cand); 1451 1452 if (auto enumInst = dynamic_cast<const ast::EnumInstType *>( 1453 variableExpr->var->get_type())) { 1454 if (enumInst->base && enumInst->base->base) { 1455 const CodeLocation &location = cand->expr->location; 1456 1457 CandidateFinder funcFinder(context, tenv); 1458 auto nameExpr = new ast::NameExpr(location, "valueE"); 1459 ResolveMode mode = {true, false, selfFinder.candidates.empty()}; 1460 funcFinder.find( nameExpr, mode ); 1461 1462 // make variableExpr itself the candidate for the value Call 1463 ExplodedArgs argExpansions; 1464 argExpansions.emplace_back(); 1465 auto &argE = argExpansions.back(); 1466 1467 argE.emplace_back(*cand, symtab); 1468 1469 CandidateList found; 1470 SemanticErrorException errors; 1471 1472 for (CandidateRef &func : funcFinder) { 1473 try { 1474 const ast::Type *funcResult = 1475 func->expr->result->stripReferences(); 1476 if (auto pointer = dynamic_cast<const ast::PointerType *>( 1477 funcResult)) { 1478 if (auto function = 1479 pointer->base.as<ast::FunctionType>()) { 1480 CandidateRef newFunc{new Candidate{*func}}; 1481 newFunc->expr = referenceToRvalueConversion( 1482 newFunc->expr, newFunc->cost); 1483 makeFunctionCandidates(variableExpr->location, 1484 newFunc, function, 1485 argExpansions, found); 1486 } 1487 } 1488 } catch (SemanticErrorException &e) { 1489 std::cerr 1490 << "Resolving value function should cause an error" 1491 << std::endl; 1492 errors.append(e); 1493 } 1494 } 1495 1496 if (found.empty()) { 1497 std::cerr << "Resolve value function should always success" 1498 << std::endl; 1499 } 1500 1501 for (CandidateRef &withFunc : found) { 1502 withFunc->cost.incSafe(); 1503 Cost cvtCost = 1504 computeApplicationConversionCost(withFunc, symtab); 1505 assert(cvtCost != Cost::infinity); 1506 1507 candidates.emplace_back(std::move(withFunc)); 1508 } 1509 } 1510 } 1511 } 1407 1512 1408 1513 void Finder::postvisit( const ast::ConstantExpr * constantExpr ) { -
src/ResolvExpr/CommonType.cc
rc17dc80 r0522ebe 397 397 result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers }; 398 398 } 399 } 400 } else if ( const ast::EnumPosType * pos = dynamic_cast< const ast::EnumPosType * >( type2 ) ) { 401 ast::BasicType::Kind kind = commonTypes[ basic->kind ][ ast::BasicType::SignedInt ]; 402 if ( 403 ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers ) 404 || widen.first ) 405 && ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers ) 406 || widen.second ) 407 ) { 408 result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers }; 399 409 } 400 410 } -
src/ResolvExpr/ConversionCost.cc
rc17dc80 r0522ebe 278 278 if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) { 279 279 conversionCostFromBasicToBasic( basicType, dstAsBasic ); 280 } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) { 280 } 281 else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) { 281 282 auto enumDecl = enumInst->base; 282 if ( auto baseType = enumDecl->base.get() ) { 283 cost = costCalc( basicType, baseType, srcIsLvalue, symtab, env ); 284 cost.incUnsafe(); 283 if ( enumDecl->base.get() ) { 284 // cost = costCalc( basicType, baseType, srcIsLvalue, symtab, env ); 285 // cost.incUnsafe(); 286 cost = Cost::infinity; 285 287 } else { 286 288 cost = Cost::unsafe; … … 365 367 cost = costCalc( integer, dst, srcIsLvalue, symtab, env ); 366 368 // } 369 if ( cost < Cost::unsafe ) { 370 cost.incSafe(); 371 } 372 } 373 374 void ConversionCost::postvisit( const ast::EnumPosType * ) { 375 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) }; 376 cost = costCalc( integer, dst, srcIsLvalue, symtab, env ); 367 377 if ( cost < Cost::unsafe ) { 368 378 cost.incSafe(); -
src/ResolvExpr/ConversionCost.h
rc17dc80 r0522ebe 72 72 void postvisit( const ast::ZeroType * zeroType ); 73 73 void postvisit( const ast::OneType * oneType ); 74 void postvisit( const ast::EnumPosType * posType ); 74 75 private: 75 76 // refactor for code resue -
src/ResolvExpr/Unify.cc
rc17dc80 r0522ebe 517 517 } 518 518 519 void postvisit( const ast::EnumPosType * posType ) { 520 // Does nothing for now. Handled in ReplacePseudoFunc 521 // Might move here in the future 522 } 523 519 524 void postvisit( const ast::TraitInstType * aggrType ) { 520 525 handleRefType( aggrType, type2 ); -
src/SymTab/Mangler.cc
rc17dc80 r0522ebe 59 59 void postvisit( const ast::QualifiedType * qualType ); 60 60 61 void postvisit( const ast::EnumPosType * posType ); 62 61 63 /// The result is the current constructed mangled name. 62 64 std::string result() const { return mangleName; } … … 277 279 assertf( decl->kind < ast::TypeDecl::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind ); 278 280 mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name; 281 } 282 283 void Mangler::postvisit( const ast::EnumPosType * pos ) { 284 postvisit( pos->instance ); 285 mangleName += "_pos"; 279 286 } 280 287 -
src/Validate/Autogen.cpp
rc17dc80 r0522ebe 206 206 ast::FunctionDecl * genLabelProto() const; 207 207 ast::FunctionDecl * genValueProto() const; 208 // ast::FunctionDecl * genValueProto2() const; 208 209 }; 209 210 … … 790 791 } 791 792 793 // ast::FunctionDecl * EnumFuncGenerator::genValueProto2() const { 794 // return genProto( "valueE", 795 // { new ast::ObjectDecl( getLocation(), "_i", new ast::EnumPosType( new ast::EnumInstType( decl ) ) )}, 796 // { new ast::ObjectDecl( getLocation(), "_ret", ast::deepCopy( decl->base ) ) } ); 797 // } 798 792 799 void EnumFuncGenerator::genAttrFuncForward() { 793 800 if ( decl->base ) { 794 801 ast::FunctionDecl *(EnumFuncGenerator::*attrProtos[3])() const = { 795 802 &EnumFuncGenerator::genPosProto, &EnumFuncGenerator::genLabelProto, 796 &EnumFuncGenerator::genValueProto }; 803 &EnumFuncGenerator::genValueProto 804 // , &EnumFuncGenerator::genValueProto2 805 }; 797 806 for ( auto & generator : attrProtos ) { 798 807 produceForwardDecl( (this->*generator)() ); -
src/Validate/ReplacePseudoFunc.cpp
rc17dc80 r0522ebe 6 6 #include "AST/Inspect.hpp" 7 7 #include "AST/Pass.hpp" 8 #include "AST/Print.hpp" 8 9 #include "AST/Stmt.hpp" 9 10 #include "Common/utility.h" 11 #include "ResolvExpr/CandidateFinder.hpp" 10 12 #include "ResolvExpr/Resolver.h" 11 13 #include "SymTab/Mangler.h" 12 14 13 #include "AST/Print.hpp"14 15 #include "ResolvExpr/CandidateFinder.hpp"16 17 15 namespace Validate { 18 16 … … 21 19 std::set<std::string> queryLabels; 22 20 std::set<std::string> queryValues; 21 22 struct ReplaceEnumInstWithPos final : public ast::WithShortCircuiting { 23 void previsit(const ast::ObjectDecl*) { visit_children = false; } 24 const ast::ObjectDecl* postvisit(const ast::ObjectDecl* decl) { 25 auto enumInst = decl->type.strict_as<ast::EnumInstType>(); 26 auto enumPos = new ast::EnumPosType(enumInst); 27 auto ret = ast::mutate_field(decl, &ast::ObjectDecl::type, enumPos); 28 ret = ast::mutate_field(ret, &ast::ObjectDecl::mangleName, 29 Mangle::mangle(ret)); 30 return ret; 31 } 32 }; 33 34 const inline std::string getValueArrayName(std::string enumName) { 35 return "values_" + enumName; 36 } 23 37 24 38 // struct AutoInit { … … 32 46 void previsit(const ast::ApplicationExpr* expr); 33 47 void previsit(const ast::CastExpr* expr); 34 void previsit(const ast::VariableExpr* 48 void previsit(const ast::VariableExpr*) { visit_children = false; } 35 49 36 50 ast::Expr const* postvisit(const ast::VariableExpr* expr); … … 66 80 auto varExpr = expr->func.as<ast::VariableExpr>(); 67 81 auto fname = ast::getFunctionName(expr); 68 if ( !varExpr || varExpr->var->linkage == ast::Linkage::Intrinsic ) { 69 if ( fname == "?{}" || fname == "?=?" ) 70 visit_children = false; 71 } 82 if (!varExpr || varExpr->var->linkage == ast::Linkage::Intrinsic) { 83 if (fname == "?{}" || fname == "?=?") visit_children = false; 84 } 72 85 73 86 if (fname == "labelE" || fname == "valueE" || fname == "posE") { … … 94 107 auto untyped = new ast::UntypedExpr( 95 108 expr->location, new ast::NameExpr(expr->location, "valueE"), 96 { std::move( expr )});109 {std::move(expr)}); 97 110 ResolvExpr::ResolveContext context{symtab, transUnit().global}; 98 111 auto result = ResolvExpr::findVoidExpression(untyped, context); 99 112 ast::ptr<ast::ApplicationExpr> ret = 100 101 return ast::deepCopy( ret);113 result.strict_as<ast::ApplicationExpr>(); 114 return ast::deepCopy(ret); 102 115 } 103 116 } … … 132 145 } 133 146 134 const 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 ) ) { 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)) { 137 152 auto prevInitExpr = prevInit->value; 138 if ( auto constInit = prevInitExpr.as< ast::ConstantExpr >()) {153 if (auto constInit = prevInitExpr.as<ast::ConstantExpr>()) { 139 154 // Assume no string literal for now 140 155 return new ast::SingleInit( 141 location, 142 ast::ConstantExpr::from_int( 143 location, constInit->intValue() + 1 ) 144 ); 156 location, ast::ConstantExpr::from_int( 157 location, constInit->intValue() + 1)); 145 158 } else { 146 159 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" ); 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"); 157 167 return prev; 158 168 } … … 167 177 auto type = enumDecl->base; 168 178 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);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); 175 185 } 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 ) ); 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))); 182 190 } else { 183 inits.emplace_back( getAutoInit( location, enumDecl->base, 184 ResolvExpr::ResolveContext{symtab, transUnit().global}, 185 inits.at( i - 1 ).as<ast::SingleInit>()) ); 191 inits.emplace_back(getAutoInit( 192 location, enumDecl->base, 193 ResolvExpr::ResolveContext{symtab, transUnit().global}, 194 inits.at(i - 1).as<ast::SingleInit>())); 186 195 } 187 196 } 188 197 labels.emplace_back(new ast::SingleInit( 189 location, ast::ConstantExpr::from_string(location, mem->name)));190 } 198 location, ast::ConstantExpr::from_string(location, mem->name))); 199 } 191 200 if (queryValues.count(enumDecl->name)) { 192 201 auto init = new ast::ListInit(location, std::move(inits)); … … 219 228 ast::ApplicationExpr const* getPseudoFuncApplication( 220 229 const CodeLocation location, ResolvExpr::ResolveContext context, 221 const ast::VariableExpr* arg, const ast::EnumDecl* base, const std::string & name) { 230 const ast::VariableExpr* arg, const ast::EnumDecl* base, 231 const std::string& name) { 222 232 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); 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 auto untyped = 244 new ast::UntypedExpr(location, new ast::NameExpr(location, "?[?]"), 245 {std::move(arrAsVar), mutatedArg}); 246 auto typedResult = ResolvExpr::findVoidExpression(untyped, context); 247 ast::ptr<ast::ApplicationExpr> ret = 248 typedResult.strict_as<ast::ApplicationExpr>(); 249 return ast::deepCopy(ret); 250 } else { 251 auto untyped = 252 new ast::UntypedExpr(location, new ast::NameExpr(location, "?[?]"), 253 {std::move(arrAsVar), arg}); 254 auto typedResult = ResolvExpr::findVoidExpression(untyped, context); 255 256 ast::ptr<ast::ApplicationExpr> ret = 257 typedResult.strict_as<ast::ApplicationExpr>(); 258 return ast::deepCopy(ret); 259 } 234 260 } 235 261 … … 250 276 const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>(); 251 277 const std::string referredName = argAsVar->name; 252 const ast::EnumInstType* argType = 253 argAsVar->type.as<const ast::EnumInstType>(); 254 if (!argType) { 278 279 if (const ast::EnumInstType* argTypeAsEnumInst = 280 argAsVar->type.as<const ast::EnumInstType>()) { 281 const ast::EnumDecl* base = argTypeAsEnumInst->base; 282 ResolvExpr::ResolveContext context{symtab, transUnit().global}; 283 // If resolvable as constant 284 for (size_t i = 0; i < base->members.size(); i++) { 285 if (base->members[i]->name == referredName) { 286 if (fname == "posE") 287 return ast::ConstantExpr::from_int(expr->location, i); 288 else if (fname == "labelE") 289 return ast::ConstantExpr::from_string(expr->location, 290 referredName); 291 else { 292 return getPseudoFuncApplication( 293 location, context, arg.get(), base, "values_"); 294 } 295 } 296 } 297 298 if (fname == "labelE") { 299 if (auto labelExpr = getPseudoFuncApplication( 300 location, context, arg.get(), base, "labels_")) { 301 return labelExpr; 302 } 303 } else if (fname == "valueE") { 304 if (auto valueExpr = getPseudoFuncApplication( 305 location, context, arg.get(), base, "values_")) { 306 return valueExpr; 307 } 308 } else { // it is position; replace itself 309 return std::move(arg.get()); 310 } 311 } else if (const ast::EnumPosType* argTypeAsPos = 312 argAsVar->type.as<const ast::EnumPosType>()) { 313 const ast::EnumDecl* base = argTypeAsPos->instance->base; 314 ResolvExpr::ResolveContext context{symtab, transUnit().global}; 315 if (fname == "labelE") { 316 if (auto labelExpr = getPseudoFuncApplication( 317 location, context, arg.get(), base, "labels_")) { 318 return labelExpr; 319 } 320 } else if (fname == "valueE") { 321 if (auto valueExpr = getPseudoFuncApplication( 322 location, context, arg.get(), base, "values_")) { 323 return valueExpr; 324 } 325 } else { // it is position; replace itself 326 return std::move(arg.get()); 327 } 328 } else { 255 329 SemanticError(argAsVar, 256 330 "Pseudo Enum Expression can only be used on an " 257 331 "enumeration instance"); 258 332 } 259 const ast::EnumDecl* base = argType->base;260 ResolvExpr::ResolveContext context{symtab, transUnit().global};261 // If resolvable as constant262 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 itself288 return std::move( arg.get() );289 }290 333 } 291 334 return expr; 292 335 } 336 337 ast::ptr<ast::Expr> reduceCastExpr(ast::ptr<ast::Expr> expr) { 338 if (auto castExpr = expr.as<ast::CastExpr>()) { 339 return reduceCastExpr(castExpr->arg); 340 } 341 return expr; 342 } 343 344 struct ReplaceEnumInst final { 345 const ast::Expr* postvisit(const ast::ApplicationExpr* expr) { 346 auto fname = ast::getFunctionName(expr); 347 if (fname != "?[?]") return expr; 348 if (expr->args.size() != 2) return expr; 349 350 auto arg1AsVar = 351 reduceCastExpr(expr->args.front()).as<ast::VariableExpr>(); 352 auto arg2AsVar = 353 reduceCastExpr(expr->args.back()).as<ast::VariableExpr>(); 354 355 if (!arg1AsVar || !arg2AsVar) return expr; 356 357 auto arg1Asecl = arg1AsVar->var.as<ast::ObjectDecl>(); 358 auto arg2Asecl = arg2AsVar->var.as<ast::ObjectDecl>(); 359 360 if (!arg1Asecl || !arg2Asecl) return expr; 361 auto arrInst = arg1Asecl->type.as<ast::ArrayType>(); 362 auto pointerInst = arg1Asecl->type.as<ast::PointerType>(); 363 if (!arrInst && !pointerInst) { 364 return expr; 365 } 366 auto enumInst = arg2Asecl->type.as<ast::EnumInstType>(); 367 if (!enumInst) return expr; 368 369 const std::string arrName = arg1Asecl->name; 370 if (arrName != getValueArrayName(enumInst->base->name)) return expr; 371 ast::Pass<ReplaceEnumInstWithPos> replacer; 372 auto rep = arg2Asecl->accept(replacer); 373 if (!rep) return expr; 374 auto mutObj = 375 ast::mutate_field(arg2AsVar, &ast::VariableExpr::var, rep); 376 auto mut = ast::mutate_field_index(expr, &ast::ApplicationExpr::args, 1, 377 mutObj); 378 return mut; 379 } 380 }; 293 381 294 382 } // namespace … … 299 387 ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit); 300 388 ast::Pass<ReplacePseudoFuncCore>::run(translationUnit); 389 ast::Pass<ReplaceEnumInst>::run(translationUnit); 301 390 } 302 391 } // namespace Validate
Note: See TracChangeset
for help on using the changeset viewer.