Changes in / [dc58e5d:7a36848]
- Location:
- src
- Files:
-
- 2 deleted
- 22 edited
-
AST/Decl.cpp (modified) (1 diff)
-
AST/Decl.hpp (modified) (2 diffs)
-
AST/Fwd.hpp (modified) (1 diff)
-
AST/Pass.hpp (modified) (1 diff)
-
AST/Pass.impl.hpp (modified) (1 diff)
-
AST/Print.cpp (modified) (1 diff)
-
AST/Type.hpp (modified) (1 diff)
-
AST/Visitor.hpp (modified) (1 diff)
-
CodeGen/GenType.cc (modified) (2 diffs)
-
Common/CodeLocationTools.cpp (modified) (1 diff)
-
GenPoly/Lvalue.cpp (modified) (2 diffs)
-
ResolvExpr/CandidateFinder.cpp (modified) (12 diffs)
-
ResolvExpr/CandidateFinder.hpp (modified) (1 diff)
-
ResolvExpr/CommonType.cc (modified) (8 diffs)
-
ResolvExpr/ConversionCost.cc (modified) (5 diffs)
-
ResolvExpr/ConversionCost.h (modified) (1 diff)
-
ResolvExpr/Unify.cc (modified) (8 diffs)
-
SymTab/Mangler.cc (modified) (2 diffs)
-
Validate/Autogen.cpp (modified) (4 diffs)
-
Validate/ImplementEnumFunc.cpp (deleted)
-
Validate/ImplementEnumFunc.hpp (deleted)
-
Validate/ReplacePseudoFunc.cpp (modified) (4 diffs)
-
Validate/module.mk (modified) (1 diff)
-
main.cc (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Decl.cpp
rdc58e5d r7a36848 169 169 } 170 170 171 const std::string EnumDecl::getUnmangeldArrayName( const ast::EnumAttribute attr ) const {172 switch( attr ) {173 case ast::EnumAttribute::Value: return "values_" + name ;174 case ast::EnumAttribute::Label: return "labels_" + name;175 default: /* Posn does not generate array */176 return "";177 }178 }179 180 171 } 181 172 -
src/AST/Decl.hpp
rdc58e5d r7a36848 303 303 }; 304 304 305 enum class EnumAttribute{ Value, Posn, Label };306 305 /// enum declaration `enum Foo { ... };` 307 306 class EnumDecl final : public AggregateDecl { … … 327 326 const char * typeString() const override { return aggrString( Enum ); } 328 327 329 const std::string getUnmangeldArrayName( const EnumAttribute attr ) const; 328 330 329 private: 331 330 EnumDecl * clone() const override { return new EnumDecl{ *this }; } -
src/AST/Fwd.hpp
rdc58e5d r7a36848 133 133 class OneType; 134 134 class GlobalScopeType; 135 class Enum AttrType;135 class EnumPosType; 136 136 137 137 class Designation; -
src/AST/Pass.hpp
rdc58e5d r7a36848 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::Enum AttrType* ) override final;224 const ast::Type * visit( const ast::EnumPosType * ) override final; 225 225 const ast::Type * visit( const ast::TraitInstType * ) override final; 226 226 const ast::Type * visit( const ast::TypeInstType * ) override final; -
src/AST/Pass.impl.hpp
rdc58e5d r7a36848 1940 1940 1941 1941 //-------------------------------------------------------------------------- 1942 // EnumAttrType 1943 template< typename core_t > 1944 const ast::Type * ast::Pass< core_t >::visit( const ast::EnumAttrType * node ) { 1945 VISIT_START( node ); 1942 // EnumPosType 1943 template< typename core_t > 1944 const ast::Type * ast::Pass< core_t >::visit( const ast::EnumPosType * node ) { 1945 VISIT_START( node ); 1946 1946 1947 VISIT_END( Type, node ); 1947 1948 } -
src/AST/Print.cpp
rdc58e5d r7a36848 1576 1576 } 1577 1577 1578 virtual const ast::Type * visit( const ast::EnumAttrType * node ) override final { 1579 preprint( node ); 1580 os << "enum attr "; 1581 if ( node->attr == ast::EnumAttribute::Label ) { 1582 os << "Label "; 1583 } else if ( node->attr == ast::EnumAttribute::Value ) { 1584 os << "Value "; 1585 } else { 1586 os << "Posn "; 1587 } 1578 virtual const ast::Type * visit( const ast::EnumPosType * node ) override final { 1579 preprint( node ); 1580 os << "enum pos with "; 1588 1581 (*(node->instance)).accept( *this ); 1589 1582 return node; -
src/AST/Type.hpp
rdc58e5d r7a36848 362 362 using EnumInstType = SueInstType<EnumDecl>; 363 363 364 class Enum AttrType final : public Type {364 class EnumPosType final : public Type { 365 365 public: 366 366 readonly<EnumInstType> instance; 367 EnumAttribute attr; 368 const Type * accept( Visitor & v ) const override { return v.visit( this ); } 369 EnumAttrType( const EnumInstType * instance, EnumAttribute attr = EnumAttribute::Posn ) 370 : instance(instance), attr(attr) {} 367 const Type * accept( Visitor & v ) const override { return v.visit( this ); } 368 EnumPosType( const EnumInstType * instance ): instance(instance) {} 371 369 372 bool match( const ast::EnumAttrType * other) const { 373 return instance->base->name == other->instance->base->name && attr == other->attr; 374 } 375 private: 376 EnumAttrType * clone() const override { return new EnumAttrType{ *this }; } 370 private: 371 EnumPosType * clone() const override { return new EnumPosType{ *this }; } 377 372 MUTATE_FRIEND 378 373 }; -
src/AST/Visitor.hpp
rdc58e5d r7a36848 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::Enum AttrType* ) = 0;121 virtual const ast::Type * visit( const ast::EnumPosType * ) = 0; 122 122 virtual const ast::Designation * visit( const ast::Designation * ) = 0; 123 123 virtual const ast::Init * visit( const ast::SingleInit * ) = 0; -
src/CodeGen/GenType.cc
rdc58e5d r7a36848 46 46 void postvisit( ast::UnionInstType const * type ); 47 47 void postvisit( ast::EnumInstType const * type ); 48 void postvisit( ast::Enum AttrType const * type );48 void postvisit( ast::EnumPosType const * type ); 49 49 void postvisit( ast::TypeInstType const * type ); 50 50 void postvisit( ast::TupleType const * type ); … … 240 240 } 241 241 242 void GenType::postvisit( ast::Enum AttrType const * type ) {242 void GenType::postvisit( ast::EnumPosType const * type ) { 243 243 postvisit( type->instance ); 244 244 } -
src/Common/CodeLocationTools.cpp
rdc58e5d r7a36848 188 188 macro(UnionInstType, Type) \ 189 189 macro(EnumInstType, Type) \ 190 macro(Enum AttrType, Type) \190 macro(EnumPosType, Type) \ 191 191 macro(TraitInstType, Type) \ 192 192 macro(TypeInstType, Type) \ -
src/GenPoly/Lvalue.cpp
rdc58e5d r7a36848 133 133 return func->linkage == ast::Linkage::Intrinsic 134 134 && lvalueFunctions.count( func->name ); 135 } 136 } 137 return false; 138 } 139 140 bool isGeneratedInstrinct( ast::Expr const * expr ) { 141 if ( auto app = dynamic_cast<ast::ApplicationExpr const *>( expr ) ) { 142 if ( app->args.size() == 2 && ast::getFunction( app )->name == "?[?]" ) { 143 auto param_1 = dynamic_cast<ast::VariableExpr const *>(app->args.front().get()); 144 if ( param_1 ) { 145 auto param_1_as_obj = param_1->var.as<ast::ObjectDecl>(); 146 return ( param_1_as_obj->name.find( "values_") != std::string::npos 147 || param_1_as_obj->name.find( "labels_" ) != std::string::npos ); 148 } 135 149 } 136 150 } … … 162 176 ast::ApplicationExpr const * expr ) { 163 177 164 if ( skip == SkipInProgress || !isIntrinsicReference( expr ) ) {178 if ( skip == SkipInProgress || !isIntrinsicReference( expr ) || isGeneratedInstrinct( expr ) ) { 165 179 return expr; 166 180 } -
src/ResolvExpr/CandidateFinder.cpp
rdc58e5d r7a36848 284 284 const CodeLocation & location, 285 285 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs & args, 286 std::vector< ArgPack > & results, std::size_t & genStart, const ResolveContext & context,286 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 287 287 unsigned nTuples = 0 288 288 ) { … … 294 294 // ^^^ need to handle the case where a tuple has a default argument 295 295 if ( ! instantiateArgument( location, 296 type, nullptr, args, results, genStart, context, nTuples ) ) return false;296 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false; 297 297 nTuples = 0; 298 298 } … … 509 509 510 510 // attempt to unify types 511 ast::ptr<ast::Type> common; 512 if ( unify( paramType, argType, env, need, have, open, common ) ) { 511 if ( unify( paramType, argType, env, need, have, open ) ) { 513 512 // add new result 514 assert( common ); 515 // auto attrType = common.as<ast::EnumAttrType>(); 516 // if ( attrType && ( attrType->attr == ast::EnumAttribute::Value ) ) { 517 // auto callExpr = new ast::UntypedExpr( 518 // expr->location, new ast::NameExpr( expr->location, "valueE"), {expr} ); 519 // CandidateFinder finder( context, env ); 520 // finder.find( callExpr ); 521 // CandidateList winners = findMinCost( finder.candidates ); 522 // if (winners.size() != 1) { 523 // SemanticError( callExpr, "Ambiguous expression in valueE" ); 524 // } 525 // CandidateRef & choice = winners.front(); 526 // choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 527 528 // results.emplace_back( 529 // i, choice->expr, 530 // std::move( env ), std::move( need ), std::move( have ), std::move( open ), 531 // nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 532 // } else { 533 results.emplace_back( 534 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 535 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 536 //} 513 results.emplace_back( 514 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 515 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 537 516 } 538 517 } … … 806 785 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>(); 807 786 if ( !instantiateArgument( location, 808 funcType->params[i], obj->init, args, results, genStart, context)) return;787 funcType->params[i], obj->init, args, results, genStart, symtab)) return; 809 788 } 810 789 goto endMatch; … … 816 795 // no default args for indirect calls 817 796 if ( !instantiateArgument( location, 818 param, nullptr, args, results, genStart, context) ) return;797 param, nullptr, args, results, genStart, symtab ) ) return; 819 798 } 820 799 … … 911 890 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) { 912 891 addAggMembers( unionInst, aggrExpr, *cand, Cost::unsafe, "" ); 913 } else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) { 914 if ( enumInst->base->base ) { 915 CandidateFinder finder( context, tenv ); 916 auto location = aggrExpr->location; 917 auto callExpr = new ast::UntypedExpr( 918 location, new ast::NameExpr( location, "valueE" ), {aggrExpr} 919 ); 920 finder.find( callExpr ); 921 CandidateList winners = findMinCost( finder.candidates ); 922 if (winners.size() != 1) { 923 SemanticError( callExpr, "Ambiguous expression in valueE" ); 924 } 925 CandidateRef & choice = winners.front(); 926 // choice->cost.incSafe(); 927 candidates.emplace_back( std::move(choice) ); 928 } 929 892 } 893 else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) { 894 if (enumInst->base && enumInst->base->base) { 895 const CodeLocation &location = cand->expr->location; 896 897 CandidateFinder funcFinder(context, tenv); 898 auto nameExpr = new ast::NameExpr(location, "valueE"); 899 ResolveMode mode = {true, false, selfFinder.candidates.empty()}; 900 funcFinder.find( nameExpr, mode ); 901 902 // make variableExpr itself the candidate for the value Call 903 ExplodedArgs argExpansions; 904 argExpansions.emplace_back(); 905 auto &argE = argExpansions.back(); 906 907 argE.emplace_back(*cand, symtab); // Use the typed name expr as param for value 908 909 CandidateList found; 910 SemanticErrorException errors; 911 912 for (CandidateRef &func : funcFinder) { 913 try { 914 const ast::Type *funcResult = 915 func->expr->result->stripReferences(); 916 if (auto pointer = dynamic_cast<const ast::PointerType *>( 917 funcResult)) { 918 if (auto function = 919 pointer->base.as<ast::FunctionType>()) { 920 CandidateRef newFunc{new Candidate{*func}}; 921 newFunc->expr = referenceToRvalueConversion( 922 newFunc->expr, newFunc->cost); 923 makeFunctionCandidates( location, 924 newFunc, function, 925 argExpansions, found ); 926 } 927 } 928 } catch (SemanticErrorException &e) { 929 std::cerr 930 << "Resolving value function should cause an error" 931 << std::endl; 932 errors.append(e); 933 } 934 } 935 936 if (found.empty()) { 937 std::cerr << "Resolve value function should always success" 938 << std::endl; 939 } 940 941 for (CandidateRef &withFunc : found) { 942 withFunc->cost.incSafe(); 943 Cost cvtCost = 944 computeApplicationConversionCost(withFunc, symtab); 945 assert(cvtCost != Cost::infinity); 946 947 candidates.emplace_back(std::move(withFunc)); 948 } 949 } 930 950 } 931 951 } … … 1394 1414 ast::Expr * newExpr = data.combine( nameExpr->location, cost ); 1395 1415 1396 bool bentConversion = false;1397 if ( auto inst = newExpr->result.as<ast::EnumInstType>() ) {1398 if ( inst->base && inst->base->base ) {1399 bentConversion = true;1400 }1401 }1402 1403 1416 CandidateRef newCand = std::make_shared<Candidate>( 1404 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, bentConversion? Cost::safe:Cost::zero,1417 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1405 1418 cost ); 1406 1419 … … 1435 1448 auto cand = new Candidate(variableExpr, tenv); 1436 1449 candidates.emplace_back(cand); 1450 1451 if (auto enumInst = dynamic_cast<const ast::EnumInstType *>( 1452 variableExpr->var->get_type())) { 1453 if (enumInst->base && enumInst->base->base) { 1454 const CodeLocation &location = cand->expr->location; 1455 1456 CandidateFinder funcFinder(context, tenv); 1457 auto nameExpr = new ast::NameExpr(location, "valueE"); 1458 ResolveMode mode = {true, false, selfFinder.candidates.empty()}; 1459 funcFinder.find( nameExpr, mode ); 1460 1461 // make variableExpr itself the candidate for the value Call 1462 ExplodedArgs argExpansions; 1463 argExpansions.emplace_back(); 1464 auto &argE = argExpansions.back(); 1465 1466 argE.emplace_back(*cand, symtab); 1467 1468 CandidateList found; 1469 SemanticErrorException errors; 1470 1471 for (CandidateRef &func : funcFinder) { 1472 try { 1473 const ast::Type *funcResult = 1474 func->expr->result->stripReferences(); 1475 if (auto pointer = dynamic_cast<const ast::PointerType *>( 1476 funcResult)) { 1477 if (auto function = 1478 pointer->base.as<ast::FunctionType>()) { 1479 CandidateRef newFunc{new Candidate{*func}}; 1480 newFunc->expr = referenceToRvalueConversion( 1481 newFunc->expr, newFunc->cost); 1482 makeFunctionCandidates(variableExpr->location, 1483 newFunc, function, 1484 argExpansions, found); 1485 } 1486 } 1487 } catch (SemanticErrorException &e) { 1488 std::cerr 1489 << "Resolving value function should cause an error" 1490 << std::endl; 1491 errors.append(e); 1492 } 1493 } 1494 1495 if (found.empty()) { 1496 std::cerr << "Resolve value function should always success" 1497 << std::endl; 1498 } 1499 1500 for (CandidateRef &withFunc : found) { 1501 withFunc->cost.incSafe(); 1502 Cost cvtCost = 1503 computeApplicationConversionCost(withFunc, symtab); 1504 assert(cvtCost != Cost::infinity); 1505 1506 candidates.emplace_back(std::move(withFunc)); 1507 } 1508 } 1509 } 1437 1510 } 1438 1511 … … 1766 1839 1767 1840 // unification run for side-effects 1768 ast::ptr<ast::Type> common; 1769 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, common ); 1841 bool canUnify = unify( toType, cand->expr->result, env, need, have, open ); 1770 1842 (void) canUnify; 1771 1843 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), … … 1792 1864 // ambiguous case, still output candidates to print in error message 1793 1865 if ( cand->cost == minExprCost && thisCost == minCastCost ) { 1794 auto commonAsEnumAttr = common.as<ast::EnumAttrType>(); 1795 if ( commonAsEnumAttr && commonAsEnumAttr->attr == ast::EnumAttribute::Value ) { 1796 1797 auto callExpr = new ast::UntypedExpr( 1798 cand->expr->location, new ast::NameExpr( cand->expr->location, "valueE"), {cand->expr} ); 1799 CandidateFinder finder( context, env ); 1800 finder.find( callExpr ); 1801 CandidateList winners = findMinCost( finder.candidates ); 1802 if (winners.size() != 1) { 1803 SemanticError( callExpr, "Ambiguous expression in valueE" ); 1804 } 1805 CandidateRef & choice = winners.front(); 1806 // assert( valueCall->result ); 1807 CandidateRef newCand = std::make_shared<Candidate>( 1808 new ast::InitExpr{ 1809 initExpr->location, 1810 // restructureCast( cand->expr, toType ), 1811 choice->expr, 1812 initAlt.designation }, 1813 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1814 inferParameters( newCand, matches ); 1815 } else { 1816 CandidateRef newCand = std::make_shared<Candidate>( 1817 new ast::InitExpr{ 1818 initExpr->location, 1819 restructureCast( cand->expr, toType ), 1820 initAlt.designation }, 1821 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1822 // currently assertions are always resolved immediately so this should have no effect. 1823 // if this somehow changes in the future (e.g. delayed by indeterminate return type) 1824 // we may need to revisit the logic. 1825 inferParameters( newCand, matches ); 1826 } 1827 } 1828 } 1866 CandidateRef newCand = std::make_shared<Candidate>( 1867 new ast::InitExpr{ 1868 initExpr->location, 1869 restructureCast( cand->expr, toType ), 1870 initAlt.designation }, 1871 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1872 // currently assertions are always resolved immediately so this should have no effect. 1873 // if this somehow changes in the future (e.g. delayed by indeterminate return type) 1874 // we may need to revisit the logic. 1875 inferParameters( newCand, matches ); 1876 } 1877 } 1829 1878 } 1830 1879 } … … 1851 1900 std::make_shared<Candidate>( 1852 1901 newExpr, copy( tenv ), ast::OpenVarSet{}, 1853 ast::AssertionSet{}, Cost:: safe, cost1902 ast::AssertionSet{}, Cost::zero, cost 1854 1903 ); 1855 1904 … … 2151 2200 } 2152 2201 2153 // get the valueE(...) ApplicationExpr that returns the enum value2154 const ast::Expr * getValueEnumCall(2155 const ast::Expr * expr,2156 const ResolvExpr::ResolveContext & context, const ast::TypeEnvironment & env ) {2157 auto callExpr = new ast::UntypedExpr(2158 expr->location, new ast::NameExpr( expr->location, "valueE"), {expr} );2159 CandidateFinder finder( context, env );2160 finder.find( callExpr );2161 CandidateList winners = findMinCost( finder.candidates );2162 if (winners.size() != 1) {2163 SemanticError( callExpr, "Ambiguous expression in valueE" );2164 }2165 CandidateRef & choice = winners.front();2166 return choice->expr;2167 }2168 2169 2202 const ast::Expr * createCondExpr( const ast::Expr * expr ) { 2170 2203 assert( expr ); -
src/ResolvExpr/CandidateFinder.hpp
rdc58e5d r7a36848 70 70 const ast::Expr * expr, Cost & cost ); 71 71 72 const ast::Expr * getValueEnumCall(const ast::Expr * expr,73 const ResolvExpr::ResolveContext & context, const ast::TypeEnvironment & env );74 72 /// Wrap an expression to convert the result to a conditional result. 75 73 const ast::Expr * createCondExpr( const ast::Expr * expr ); -
src/ResolvExpr/CommonType.cc
rdc58e5d r7a36848 385 385 } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) { 386 386 const ast::EnumDecl* enumDecl = enumInst->base; 387 if ( !enumDecl->base ) { 387 if ( enumDecl->base ) { 388 result = enumDecl->base.get(); 389 } else { 388 390 ast::BasicType::Kind kind = commonTypes[ basic->kind ][ ast::BasicType::SignedInt ]; 389 391 if ( … … 396 398 } 397 399 } 398 } else if ( auto type2AsAttr = dynamic_cast< const ast::EnumAttrType * >( type2 ) ) { 399 if ( type2AsAttr->attr == ast::EnumAttribute::Posn ) { 400 ast::BasicType::Kind kind = commonTypes[ basic->kind ][ ast::BasicType::SignedInt ]; 401 if ( 402 ( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers ) 403 || widen.first ) 404 && ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers ) 405 || widen.second ) 406 ) { 407 result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers }; 408 } 409 } 400 } else if ( 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 } 410 410 } 411 411 } … … 426 426 result = voidPtr; 427 427 add_qualifiers( result, oPtr->qualifiers ); 428 } 429 430 // For a typed enum, we want to unify type1 with the base type of the enum 431 bool tryResolveWithTypedEnum( const ast::Type * type1 ) { 432 if (auto enumInst = dynamic_cast<const ast::EnumInstType *> (type2) ) { 433 ast::OpenVarSet newOpen{ open }; 434 if (enumInst->base->base 435 && unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen)) { 436 result = type1; 437 return true; 438 } 439 } 440 return false; 428 441 } 429 442 … … 594 607 result = pointer; 595 608 add_qualifiers( result, type2->qualifiers ); 596 } 597 } 598 599 void postvisit( const ast::ArrayType * arr ) {} 609 } else { 610 tryResolveWithTypedEnum( pointer ); 611 } 612 } 613 614 void postvisit( const ast::ArrayType * arr ) { 615 // xxx - does it make sense? 616 tryResolveWithTypedEnum( arr ); 617 } 600 618 601 619 void postvisit( const ast::ReferenceType * ref ) { … … 641 659 } 642 660 643 void postvisit( const ast::FunctionType * func) {} 644 645 void postvisit( const ast::StructInstType * inst ) {} 646 647 void postvisit( const ast::UnionInstType * inst ) {} 661 void postvisit( const ast::FunctionType * func) { 662 tryResolveWithTypedEnum( func ); 663 } 664 665 void postvisit( const ast::StructInstType * inst ) { 666 tryResolveWithTypedEnum( inst ); 667 } 668 669 void postvisit( const ast::UnionInstType * inst ) { 670 tryResolveWithTypedEnum( inst ); 671 } 648 672 649 673 void postvisit( const ast::EnumInstType * enumInst ) { 650 if ( enumInst->base && !enumInst->base->base ) { 651 auto basicType = new ast::BasicType( ast::BasicType::UnsignedInt ); 652 result = commonType( basicType, type2, tenv, need, have, open, widen); 653 } 654 } 655 656 void postvisit( const ast::EnumAttrType * ) {} 674 // if ( dynamic_cast<const ast::EnumPosType *>(enumInst) ) { 675 // result = enumInst; 676 // } else 677 if (!dynamic_cast<const ast::EnumInstType *>(type2)) { 678 result = commonType( type2, enumInst, tenv, need, have, open, widen); 679 } 680 } 681 682 void postvisit( const ast::EnumPosType * enumPos ) { 683 if ( auto type2AsPos = dynamic_cast<const ast::EnumPosType *>(type2) ) { 684 // result = commonType( type2AsPos->instance, enumPos->instance, tenv, need, have, open, widen ); 685 // result = enumPos; 686 if ( enumPos->instance->base->name == type2AsPos->instance->base->name ) { 687 result = type2; 688 } 689 } else if ( dynamic_cast<const ast::BasicType *>(type2) ) { 690 result = type2; 691 } 692 } 657 693 658 694 void postvisit( const ast::TraitInstType * ) {} … … 660 696 void postvisit( const ast::TypeInstType * ) {} 661 697 662 void postvisit( const ast::TupleType * tuple ) {} 698 void postvisit( const ast::TupleType * tuple ) { 699 tryResolveWithTypedEnum( tuple ); 700 } 663 701 664 702 void postvisit( const ast::VarArgsType * ) {} … … 677 715 } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) { 678 716 const ast::EnumDecl * enumDecl = enumInst->base; 679 if ( !enumDecl->base ) { 717 if ( enumDecl->base ) { 718 if ( tryResolveWithTypedEnum( zero ) ) 719 add_qualifiers( result, zero->qualifiers ); 720 } else { 680 721 if ( widen.second || zero->qualifiers <= type2->qualifiers ) { 681 722 result = type2; … … 697 738 ast::BasicType::SignedInt, one->qualifiers | type2->qualifiers }; 698 739 } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) { 699 const ast::EnumDecl * enumDecl = enumInst->base; 700 if ( !enumDecl->base ) { 740 const ast::EnumDecl * enumBase = enumInst->base; 741 if ( enumBase->base ) { 742 if ( tryResolveWithTypedEnum( one )) 743 add_qualifiers( result, one->qualifiers ); 744 } else { 701 745 if ( widen.second || one->qualifiers <= type2->qualifiers ) { 702 746 result = type2; -
src/ResolvExpr/ConversionCost.cc
rdc58e5d r7a36848 278 278 if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) { 279 279 conversionCostFromBasicToBasic( basicType, dstAsBasic ); 280 } else if ( dynamic_cast< const ast::EnumAttrType *>(dst) ) { 280 } 281 else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) { 282 auto enumDecl = enumInst->base; 283 if ( enumDecl->base.get() ) { 284 // cost = costCalc( basicType, baseType, srcIsLvalue, symtab, env ); 285 // cost.incUnsafe(); 286 cost = Cost::infinity; 287 } else { 288 cost = Cost::unsafe; 289 } 290 } else if ( dynamic_cast< const ast::EnumPosType *>(dst) ) { 281 291 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) }; 282 292 cost = costCalc( basicType, integer, srcIsLvalue, symtab, env ); 283 } else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {284 if ( dstAsEnumInst->base && !dstAsEnumInst->base->base ) {285 cost = Cost::zero;286 cost.incUnsafe();287 }288 293 } 289 294 } … … 361 366 } 362 367 363 void ConversionCost::postvisit( const ast::EnumInstType * inst ) { 364 if ( inst->base && inst->base->base ) { 365 if ( auto dstAsAttr = dynamic_cast<const ast::EnumAttrType *>( dst ) ) { 366 auto instAsAttr = ast::EnumAttrType( inst, dstAsAttr->attr ); 367 if ( instAsAttr.match(dstAsAttr) ) { 368 cost.incUnsafe(); 369 } 370 371 } else if ( auto dstAsInst = dynamic_cast<const ast::EnumInstType *>( dst ) ) { 372 if (inst->base && dstAsInst->base) { 373 if (inst->base == dstAsInst->base) { 374 cost.incUnsafe(); 375 } 376 } 377 } else { 378 auto instAsVal = ast::EnumAttrType( inst, ast::EnumAttribute::Value ); 379 cost = costCalc( &instAsVal, dst, srcIsLvalue, symtab, env ); 380 if ( cost < Cost::infinity ) { 381 cost.incUnsafe(); 382 } 383 } 384 return; 385 } 368 void ConversionCost::postvisit( const ast::EnumInstType * ) { 386 369 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) }; 387 370 cost = costCalc( integer, dst, srcIsLvalue, symtab, env ); … … 391 374 } 392 375 393 void ConversionCost::postvisit( const ast::EnumAttrType * src ) { 394 auto dstAsEnumAttrType = dynamic_cast<const ast::EnumAttrType *>(dst); 395 if ( src->attr == ast::EnumAttribute::Label ) { 396 if ( dstAsEnumAttrType && dstAsEnumAttrType->attr == ast::EnumAttribute::Label ) { 397 cost = costCalc( src->instance, dstAsEnumAttrType->instance, srcIsLvalue, symtab, env ); 398 } 399 // Add Conversion To String 400 } else if ( src->attr == ast::EnumAttribute::Value ) { 401 if ( dstAsEnumAttrType && dstAsEnumAttrType->attr == ast::EnumAttribute::Value) { 402 cost = costCalc( src->instance, dstAsEnumAttrType->instance, srcIsLvalue, symtab, env ); 403 } else { 404 auto baseType = src->instance->base->base; 405 cost = costCalc( baseType, dst, srcIsLvalue, symtab, env ); 406 if ( cost < Cost::infinity ) { 407 cost.incUnsafe(); 408 } 409 } 410 } else { // ast::EnumAttribute::Posn 411 if ( auto dstBase = dynamic_cast<const ast::EnumInstType *>( dst ) ) { 412 cost = costCalc( src->instance, dstBase, srcIsLvalue, symtab, env ); 413 if ( cost < Cost::unsafe ) cost.incSafe(); 414 } else { 415 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) }; 416 cost = costCalc( integer, dst, srcIsLvalue, symtab, env ); 417 if ( cost < Cost::unsafe ) { 418 cost.incSafe(); 419 } 420 } 421 } 376 void ConversionCost::postvisit( const ast::EnumPosType * src ) { 377 if ( dynamic_cast<const ast::EnumPosType *>( dst ) ) { 378 // cost = costCalc( src->instance, dstBase->instance, srcIsLvalue, symtab, env ); 379 // if ( cost < Cost::unsafe ) cost.incSafe(); 380 cost = Cost::zero; 381 } else if ( auto dstBase = dynamic_cast<const ast::EnumInstType *>( dst ) ) { 382 cost = costCalc( src->instance, dstBase, srcIsLvalue, symtab, env ); 383 if ( cost < Cost::unsafe ) cost.incSafe(); 384 } else { 385 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) }; 386 cost = costCalc( integer, dst, srcIsLvalue, symtab, env ); 387 if ( cost < Cost::unsafe ) { 388 cost.incSafe(); 389 } 390 } 391 422 392 } 423 393 … … 496 466 cost.incSafe( maxIntCost + 2 ); 497 467 // assuming 0p is supposed to be used for pointers? 498 } else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {499 if ( dstAsEnumInst->base && !dstAsEnumInst->base->base ) {500 cost = Cost::zero;501 cost.incUnsafe();502 }503 468 } 504 469 } … … 518 483 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] ); 519 484 } 520 } else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {521 if ( dstAsEnumInst->base && !dstAsEnumInst->base->base ) {522 cost = Cost::zero;523 cost.incUnsafe();524 }525 485 } 526 486 } -
src/ResolvExpr/ConversionCost.h
rdc58e5d r7a36848 72 72 void postvisit( const ast::ZeroType * zeroType ); 73 73 void postvisit( const ast::OneType * oneType ); 74 void postvisit( const ast::Enum AttrType * posType );74 void postvisit( const ast::EnumPosType * posType ); 75 75 private: 76 76 // refactor for code resue -
src/ResolvExpr/Unify.cc
rdc58e5d r7a36848 274 274 void previsit( const ast::Node * ) { visit_children = false; } 275 275 276 void postvisit( const ast::VoidType * vt) { 277 result = dynamic_cast< const ast::VoidType * >( type2 ) 278 || tryToUnifyWithEnumValue(vt, type2, tenv, need, have, open, noWiden()); 279 ; 276 void postvisit( const ast::VoidType * ) { 277 result = dynamic_cast< const ast::VoidType * >( type2 ); 280 278 } 281 279 … … 284 282 result = basic->kind == basic2->kind; 285 283 } 286 result = result || tryToUnifyWithEnumValue(basic, type2, tenv, need, have, open, noWiden());287 284 } 288 285 … … 293 290 noWiden()); 294 291 } 295 result = result || tryToUnifyWithEnumValue(pointer, type2, tenv, need, have, open, noWiden());296 292 } 297 293 … … 311 307 312 308 result = unifyExact( 313 array->base, array2->base, tenv, need, have, open, noWiden()) 314 || tryToUnifyWithEnumValue(array, type2, tenv, need, have, open, noWiden()); 309 array->base, array2->base, tenv, need, have, open, noWiden()); 315 310 } 316 311 … … 404 399 } 405 400 406 bool tryToUnifyWithEnumValue( const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,407 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,408 WidenMode widen) {409 if ( auto attrType2 = dynamic_cast<const ast::EnumAttrType *>(type2)) {410 if (attrType2->attr == ast::EnumAttribute::Value) {411 return unifyExact( type1, attrType2->instance->base->base, env, need, have, open,412 widen);413 } else if (attrType2->attr == ast::EnumAttribute::Posn) {414 return unifyExact( type1, attrType2->instance, env, need, have, open, widen );415 }416 }417 return false;418 }419 420 401 public: 421 402 void postvisit( const ast::FunctionType * func ) { … … 526 507 void postvisit( const ast::StructInstType * aggrType ) { 527 508 handleGenericRefType( aggrType, type2 ); 528 result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());529 509 } 530 510 531 511 void postvisit( const ast::UnionInstType * aggrType ) { 532 512 handleGenericRefType( aggrType, type2 ); 533 result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());534 513 } 535 514 536 515 void postvisit( const ast::EnumInstType * aggrType ) { 537 516 handleRefType( aggrType, type2 ); 538 result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden()); 539 } 540 541 void postvisit( const ast::EnumAttrType * enumAttr ) { 517 } 518 519 void postvisit( const ast::EnumPosType * posType ) { 542 520 // Lazy approach for now 543 if ( auto otherPos = dynamic_cast< const ast::EnumAttrType *>(type2) ) {544 if ( enumAttr->match(otherPos)) {545 result = otherPos;546 }547 } 521 auto otherPos = dynamic_cast< const ast::EnumPosType *>(type2); 522 if ( otherPos ) { 523 if ( otherPos->instance->base->name == posType->instance->base->name ) 524 result = otherPos; 525 } 548 526 } 549 527 550 528 void postvisit( const ast::TraitInstType * aggrType ) { 551 529 handleRefType( aggrType, type2 ); 552 result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden());553 530 } 554 531 … … 559 536 this->result = otherInst; 560 537 } 561 result = result || tryToUnifyWithEnumValue(typeInst, type2, tenv, need, have, open, noWiden());562 538 } 563 539 … … 634 610 auto types2 = flatten( flat2 ); 635 611 636 result = unifyList( types, types2, tenv, need, have, open ) 637 || tryToUnifyWithEnumValue(tuple, type2, tenv, need, have, open, noWiden()); 638 } 639 640 void postvisit( const ast::VarArgsType * vat) { 641 result = dynamic_cast< const ast::VarArgsType * >( type2 ) 642 || tryToUnifyWithEnumValue(vat, type2, tenv, need, have, open, noWiden()); 643 } 644 645 void postvisit( const ast::ZeroType * zt) { 646 result = dynamic_cast< const ast::ZeroType * >( type2 ) 647 || tryToUnifyWithEnumValue(zt, type2, tenv, need, have, open, noWiden()); 648 } 649 650 void postvisit( const ast::OneType * ot) { 651 result = dynamic_cast< const ast::OneType * >( type2 ) 652 || tryToUnifyWithEnumValue(ot, type2, tenv, need, have, open, noWiden()); 612 result = unifyList( types, types2, tenv, need, have, open ); 613 } 614 615 void postvisit( const ast::VarArgsType * ) { 616 result = dynamic_cast< const ast::VarArgsType * >( type2 ); 617 } 618 619 void postvisit( const ast::ZeroType * ) { 620 result = dynamic_cast< const ast::ZeroType * >( type2 ); 621 } 622 623 void postvisit( const ast::OneType * ) { 624 result = dynamic_cast< const ast::OneType * >( type2 ); 653 625 } 654 626 }; -
src/SymTab/Mangler.cc
rdc58e5d r7a36848 58 58 void postvisit( const ast::OneType * oneType ); 59 59 void postvisit( const ast::QualifiedType * qualType ); 60 void postvisit( const ast::EnumAttrType * posType ); 60 61 void postvisit( const ast::EnumPosType * posType ); 61 62 62 63 /// The result is the current constructed mangled name. … … 280 281 } 281 282 282 void Mangler::postvisit( const ast::EnumAttrType * enumAttr ) { 283 postvisit( enumAttr->instance ); 284 // mangleName += "_pos"; 285 switch ( enumAttr->attr ) 286 { 287 case ast::EnumAttribute::Label: 288 mangleName += "_label_"; 289 break; 290 case ast::EnumAttribute::Posn: 291 mangleName += "_posn_"; 292 break; 293 case ast::EnumAttribute::Value: 294 mangleName += "_value_"; 295 break; 296 } 297 283 void Mangler::postvisit( const ast::EnumPosType * pos ) { 284 postvisit( pos->instance ); 285 mangleName += "_pos"; 298 286 } 299 287 -
src/Validate/Autogen.cpp
rdc58e5d r7a36848 196 196 197 197 bool shouldAutogen() const final { return true; } 198 void genAttrFuncForward(); 199 void genPosFunctions(); 198 200 private: 199 201 void genFuncBody( ast::FunctionDecl * decl ) final; 200 202 void genFieldCtors() final; 201 203 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(); 202 216 }; 203 217 … … 242 256 enumInst.base = enumDecl; 243 257 EnumFuncGenerator gen( enumDecl, &enumInst, functionNesting ); 258 if ( enumDecl->base ) { 259 gen.genAttrFuncForward(); 260 gen.genPosFunctions(); 261 } 244 262 gen.generateAndAppendFunctions( declsToAddAfter ); 245 263 } … … 400 418 } 401 419 402 /// Use the current type T to create `void ^?{}(T & _dst)`.420 /// Use the current type T to create `void ?{}(T & _dst)`. 403 421 ast::FunctionDecl * FuncGenerator::genDtorProto() const { 404 422 // The destructor must be mutex on a concurrent type. … … 759 777 } 760 778 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 addOneExpr 868 ); 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::genPredProto 887 // ,&EnumFuncGenerator::genSuccPosProto, 888 // &EnumFuncGenerator::genPredPosProto 889 }; 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 761 906 void TypeFuncGenerator::genFieldCtors() { 762 907 // Opaque types do not have field constructors. -
src/Validate/ReplacePseudoFunc.cpp
rdc58e5d r7a36848 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); … … 56 375 return ast::deepCopy(ret); 57 376 } else if (auto posType = 58 argAsDecl->type.as<ast::EnumAttrType>()) { 59 std::cerr << "PseudoFunc: succ/pred should not be applied on EnumAttrType directly" << std::endl; 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); 60 415 } 61 416 } … … 69 424 70 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 71 432 ast::Pass<ReplaceSuccAndPred>::run(translationUnit); 72 433 } -
src/Validate/module.mk
rdc58e5d r7a36848 54 54 Validate/VerifyCtorDtorAssign.hpp \ 55 55 Validate/ReplacePseudoFunc.cpp \ 56 Validate/ReplacePseudoFunc.hpp \ 57 Validate/ImplementEnumFunc.cpp \ 58 Validate/ImplementEnumFunc.hpp 56 Validate/ReplacePseudoFunc.hpp 59 57 60 58 SRCDEMANGLE += $(SRC_VALIDATE) -
src/main.cc
rdc58e5d r7a36848 66 66 #include "Tuples/Tuples.h" // for expandMemberTuples, expan... 67 67 #include "Validate/Autogen.hpp" // for autogenerateRoutines 68 #include "Validate/ImplementEnumFunc.hpp" // for implementEnumFunc68 // #include "Validate/ImplementEnumFunc.hpp" // for implementEnumFunc 69 69 #include "Validate/CompoundLiteral.hpp" // for handleCompoundLiterals 70 70 #include "Validate/EliminateTypedef.hpp" // for eliminateTypedef … … 333 333 334 334 PASS( "Generate Autogen Routines", Validate::autogenerateRoutines, transUnit ); 335 PASS( "Generate Enum Attributes Functions", Validate::implementEnumFunc, transUnit );335 // PASS( "Generate Enum Attributes Functions", Validate::implementEnumFunc, transUnit ); 336 336 337 337 PASS( "Implement Actors", Concurrency::implementActors, transUnit ); … … 383 383 PASS( "Replace Pseudo Func", Validate::replacePseudoFunc, transUnit ); 384 384 DUMP( reppseu, std::move( transUnit ) ); 385 PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() ); // Here385 PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() ); 386 386 PASS( "Erase With", ResolvExpr::eraseWith, transUnit ); 387 387
Note:
See TracChangeset
for help on using the changeset viewer.