Changes in / [a4da45e:022bce0]
- Files:
-
- 1 deleted
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Fwd.hpp
ra4da45e r022bce0 133 133 class OneType; 134 134 class GlobalScopeType; 135 class EnumPosType;136 135 137 136 class Designation; -
src/AST/Pass.hpp
ra4da45e r022bce0 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;225 224 const ast::Type * visit( const ast::TraitInstType * ) override final; 226 225 const ast::Type * visit( const ast::TypeInstType * ) override final; -
src/AST/Pass.impl.hpp
ra4da45e r022bce0 1986 1986 1987 1987 //-------------------------------------------------------------------------- 1988 // EnumPosType1989 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 //--------------------------------------------------------------------------1997 1988 // TraitInstType 1998 1989 template< typename core_t > -
src/AST/Print.cpp
ra4da45e r022bce0 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 1585 1578 virtual const ast::Type * visit( const ast::TraitInstType * node ) override final { 1586 1579 preprint( node ); -
src/AST/Type.hpp
ra4da45e r022bce0 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_FRIEND373 };374 375 364 /// An instance of a trait type. 376 365 class TraitInstType final : public BaseInstType { -
src/AST/Visitor.hpp
ra4da45e r022bce0 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;122 121 virtual const ast::Designation * visit( const ast::Designation * ) = 0; 123 122 virtual const ast::Init * visit( const ast::SingleInit * ) = 0; -
src/CodeGen/GenType.cc
ra4da45e r022bce0 46 46 void postvisit( ast::UnionInstType const * type ); 47 47 void postvisit( ast::EnumInstType const * type ); 48 void postvisit( ast::EnumPosType const * type );49 48 void postvisit( ast::TypeInstType const * type ); 50 49 void postvisit( ast::TupleType const * type ); … … 240 239 } 241 240 242 void GenType::postvisit( ast::EnumPosType const * type ) {243 postvisit( type->instance );244 }245 246 241 void GenType::postvisit( ast::TypeInstType const * type ) { 247 242 assertf( !options.genC, "TypeInstType should not reach code generation." ); -
src/Common/CodeLocationTools.cpp
ra4da45e r022bce0 188 188 macro(UnionInstType, Type) \ 189 189 macro(EnumInstType, Type) \ 190 macro(EnumPosType, Type) \191 190 macro(TraitInstType, Type) \ 192 191 macro(TypeInstType, Type) \ -
src/Parser/parser.yy
ra4da45e r022bce0 3022 3022 | assertion_list 3023 3023 { $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); } 3024 | ENUM '(' identifier_or_type_name ')' identifier_or_type_name new_type_class type_initializer_opt assertion_list_opt3025 {3026 typedefTable.addToScope( *$3, TYPEDIMname, "type_parameter 4" );3027 typedefTable.addToScope( *$5, TYPEDIMname, "type_parameter 5" );3028 $$ = DeclarationNode::newTypeParam( $6, $5 )->addTypeInitializer( $7 )->addAssertions( $8 );3029 }3030 3024 ; 3031 3025 -
src/ResolvExpr/CandidateFinder.cpp
ra4da45e r022bce0 891 891 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) { 892 892 addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" ); 893 } 894 else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) { 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 } 893 } else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) { 894 // The Attribute Arrays are not yet generated, need to proxy them 895 // as attribute function call 896 const CodeLocation & location = cand->expr->location; 897 if ( enumInst->base && enumInst->base->base ) { 898 auto valueName = new ast::NameExpr(location, "valueE"); 899 auto untypedValueCall = new ast::UntypedExpr( 900 location, valueName, { aggrExpr } ); 901 auto result = ResolvExpr::findVoidExpression( untypedValueCall, context ); 902 assert( result.get() ); 903 CandidateRef newCand = std::make_shared<Candidate>( 904 *cand, result, Cost::safe ); 905 candidates.emplace_back( std::move( newCand ) ); 906 } 951 907 } 952 908 } … … 1444 1400 } 1445 1401 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 } 1402 void Finder::postvisit( const ast::VariableExpr * variableExpr ) { 1403 // not sufficient to just pass `variableExpr` here, type might have changed since 1404 addCandidate( variableExpr, tenv ); 1405 } 1512 1406 1513 1407 void Finder::postvisit( const ast::ConstantExpr * constantExpr ) { -
src/ResolvExpr/CommonType.cc
ra4da45e r022bce0 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 };409 399 } 410 400 } -
src/ResolvExpr/ConversionCost.cc
ra4da45e r022bce0 278 278 if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) { 279 279 conversionCostFromBasicToBasic( basicType, dstAsBasic ); 280 } 281 else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) { 280 } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) { 282 281 auto enumDecl = enumInst->base; 283 if ( enumDecl->base.get() ) { 284 // cost = costCalc( basicType, baseType, srcIsLvalue, symtab, env ); 285 // cost.incUnsafe(); 286 cost = Cost::infinity; 282 if ( auto baseType = enumDecl->base.get() ) { 283 cost = costCalc( basicType, baseType, srcIsLvalue, symtab, env ); 284 cost.incUnsafe(); 287 285 } else { 288 286 cost = Cost::unsafe; … … 367 365 cost = costCalc( integer, dst, srcIsLvalue, symtab, env ); 368 366 // } 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 );377 367 if ( cost < Cost::unsafe ) { 378 368 cost.incSafe(); -
src/ResolvExpr/ConversionCost.h
ra4da45e r022bce0 72 72 void postvisit( const ast::ZeroType * zeroType ); 73 73 void postvisit( const ast::OneType * oneType ); 74 void postvisit( const ast::EnumPosType * posType );75 74 private: 76 75 // refactor for code resue -
src/ResolvExpr/Unify.cc
ra4da45e r022bce0 517 517 } 518 518 519 void postvisit( const ast::EnumPosType * posType ) {520 // Does nothing for now. Handled in ReplacePseudoFunc521 // Might move here in the future522 }523 524 519 void postvisit( const ast::TraitInstType * aggrType ) { 525 520 handleRefType( aggrType, type2 ); -
src/SymTab/Mangler.cc
ra4da45e r022bce0 59 59 void postvisit( const ast::QualifiedType * qualType ); 60 60 61 void postvisit( const ast::EnumPosType * posType );62 63 61 /// The result is the current constructed mangled name. 64 62 std::string result() const { return mangleName; } … … 279 277 assertf( decl->kind < ast::TypeDecl::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind ); 280 278 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";286 279 } 287 280 -
src/Validate/Autogen.cpp
ra4da45e r022bce0 205 205 ast::FunctionDecl * genLabelProto() const; 206 206 ast::FunctionDecl * genValueProto() const; 207 // ast::FunctionDecl * genValueProto2() const;208 207 }; 209 208 … … 790 789 } 791 790 792 // ast::FunctionDecl * EnumFuncGenerator::genValueProto2() const {793 // return genProto( "valueE",794 // { new ast::ObjectDecl( getLocation(), "_i", new ast::EnumPosType( new ast::EnumInstType( decl ) ) )},795 // { new ast::ObjectDecl( getLocation(), "_ret", ast::deepCopy( decl->base ) ) } );796 // }797 798 791 void EnumFuncGenerator::genAttrFuncForward() { 799 792 if ( decl->base ) { 800 793 ast::FunctionDecl *(EnumFuncGenerator::*attrProtos[3])() const = { 801 794 &EnumFuncGenerator::genPosProto, &EnumFuncGenerator::genLabelProto, 802 &EnumFuncGenerator::genValueProto 803 // , &EnumFuncGenerator::genValueProto2 804 }; 795 &EnumFuncGenerator::genValueProto }; 805 796 for ( auto & generator : attrProtos ) { 806 797 produceForwardDecl( (this->*generator)() ); -
src/Validate/ReplacePseudoFunc.cpp
ra4da45e r022bce0 6 6 #include "AST/Inspect.hpp" 7 7 #include "AST/Pass.hpp" 8 #include "AST/Print.hpp"9 8 #include "AST/Stmt.hpp" 10 9 #include "Common/utility.h" 11 #include "ResolvExpr/CandidateFinder.hpp"12 10 #include "ResolvExpr/Resolver.h" 13 11 #include "SymTab/Mangler.h" 14 12 13 #include "AST/Print.hpp" 14 15 #include "ResolvExpr/CandidateFinder.hpp" 16 15 17 namespace Validate { 16 18 … … 19 21 std::set<std::string> queryLabels; 20 22 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 }37 23 38 24 // struct AutoInit { … … 46 32 void previsit(const ast::ApplicationExpr* expr); 47 33 void previsit(const ast::CastExpr* expr); 48 void previsit(const ast::VariableExpr* ) { visit_children = false; }34 void previsit(const ast::VariableExpr* ) { visit_children = false; } 49 35 50 36 ast::Expr const* postvisit(const ast::VariableExpr* expr); … … 80 66 auto varExpr = expr->func.as<ast::VariableExpr>(); 81 67 auto fname = ast::getFunctionName(expr); 82 if (!varExpr || varExpr->var->linkage == ast::Linkage::Intrinsic) { 83 if (fname == "?{}" || fname == "?=?") visit_children = false; 84 } 68 if ( !varExpr || varExpr->var->linkage == ast::Linkage::Intrinsic ) { 69 if ( fname == "?{}" || fname == "?=?" ) 70 visit_children = false; 71 } 85 72 86 73 if (fname == "labelE" || fname == "valueE" || fname == "posE") { … … 107 94 auto untyped = new ast::UntypedExpr( 108 95 expr->location, new ast::NameExpr(expr->location, "valueE"), 109 { std::move(expr)});96 { std::move( expr ) }); 110 97 ResolvExpr::ResolveContext context{symtab, transUnit().global}; 111 98 auto result = ResolvExpr::findVoidExpression(untyped, context); 112 99 ast::ptr<ast::ApplicationExpr> ret = 113 result.strict_as<ast::ApplicationExpr>();114 return ast::deepCopy( ret);100 result.strict_as<ast::ApplicationExpr>(); 101 return ast::deepCopy( ret ); 115 102 } 116 103 } … … 145 132 } 146 133 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)) { 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 ) ) { 152 137 auto prevInitExpr = prevInit->value; 153 if ( auto constInit = prevInitExpr.as<ast::ConstantExpr>()) {138 if ( auto constInit = prevInitExpr.as< ast::ConstantExpr >() ) { 154 139 // Assume no string literal for now 155 140 return new ast::SingleInit( 156 location, ast::ConstantExpr::from_int( 157 location, constInit->intValue() + 1)); 141 location, 142 ast::ConstantExpr::from_int( 143 location, constInit->intValue() + 1 ) 144 ); 158 145 } else { 159 146 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"); 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" ); 167 157 return prev; 168 158 } … … 177 167 auto type = enumDecl->base; 178 168 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);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 ); 185 175 } 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))); 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 ) ); 190 182 } else { 191 inits.emplace_back(getAutoInit( 192 location, enumDecl->base, 193 ResolvExpr::ResolveContext{symtab, transUnit().global}, 194 inits.at(i - 1).as<ast::SingleInit>())); 183 inits.emplace_back( getAutoInit( location, enumDecl->base, 184 ResolvExpr::ResolveContext{symtab, transUnit().global}, 185 inits.at( i - 1 ).as<ast::SingleInit>()) ); 195 186 } 196 187 } 197 188 labels.emplace_back(new ast::SingleInit( 198 199 } 189 location, ast::ConstantExpr::from_string(location, mem->name))); 190 } 200 191 if (queryValues.count(enumDecl->name)) { 201 192 auto init = new ast::ListInit(location, std::move(inits)); … … 228 219 ast::ApplicationExpr const* getPseudoFuncApplication( 229 220 const CodeLocation location, ResolvExpr::ResolveContext context, 230 const ast::VariableExpr* arg, const ast::EnumDecl* base, 231 const std::string& name) { 221 const ast::VariableExpr* arg, const ast::EnumDecl* base, const std::string & name) { 232 222 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 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 } 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); 260 234 } 261 235 … … 276 250 const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>(); 277 251 const std::string referredName = argAsVar->name; 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 { 252 const ast::EnumInstType* argType = 253 argAsVar->type.as<const ast::EnumInstType>(); 254 if (!argType) { 329 255 SemanticError(argAsVar, 330 256 "Pseudo Enum Expression can only be used on an " 331 257 "enumeration instance"); 332 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 } 333 290 } 334 291 return expr; 335 292 } 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 };381 293 382 294 } // namespace … … 387 299 ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit); 388 300 ast::Pass<ReplacePseudoFuncCore>::run(translationUnit); 389 ast::Pass<ReplaceEnumInst>::run(translationUnit);390 301 } 391 302 } // namespace Validate
Note: See TracChangeset
for help on using the changeset viewer.