Changeset af746cc
- Timestamp:
- Apr 15, 2024, 12:03:53 PM (17 months ago)
- Branches:
- master
- Children:
- dc58e5d
- Parents:
- d9bad51
- Location:
- src
- Files:
-
- 2 added
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Decl.cpp
rd9bad51 raf746cc 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 171 180 } 172 181 -
src/AST/Decl.hpp
rd9bad51 raf746cc 303 303 }; 304 304 305 enum class EnumAttribute{ Value, Posn, Label }; 305 306 /// enum declaration `enum Foo { ... };` 306 307 class EnumDecl final : public AggregateDecl { … … 326 327 const char * typeString() const override { return aggrString( Enum ); } 327 328 328 329 const std::string getUnmangeldArrayName( const EnumAttribute attr ) const; 329 330 private: 330 331 EnumDecl * clone() const override { return new EnumDecl{ *this }; } -
src/AST/Fwd.hpp
rd9bad51 raf746cc 133 133 class OneType; 134 134 class GlobalScopeType; 135 class Enum PosType;135 class EnumAttrType; 136 136 137 137 class Designation; -
src/AST/Pass.hpp
rd9bad51 raf746cc 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 PosType* ) override final;224 const ast::Type * visit( const ast::EnumAttrType * ) 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
rd9bad51 raf746cc 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 1988 // EnumAttrType 1989 template< typename core_t > 1990 const ast::Type * ast::Pass< core_t >::visit( const ast::EnumAttrType * node ) { 1991 VISIT_START( node ); 1993 1992 VISIT_END( Type, node ); 1994 1993 } -
src/AST/Print.cpp
rd9bad51 raf746cc 1576 1576 } 1577 1577 1578 virtual const ast::Type * visit( const ast::EnumPosType * node ) override final { 1579 preprint( node ); 1580 os << "enum pos with "; 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 } 1581 1588 (*(node->instance)).accept( *this ); 1582 1589 return node; -
src/AST/Type.hpp
rd9bad51 raf746cc 362 362 using EnumInstType = SueInstType<EnumDecl>; 363 363 364 class Enum PosType final : public Type {364 class EnumAttrType final : public Type { 365 365 public: 366 366 readonly<EnumInstType> instance; 367 const Type * accept( Visitor & v ) const override { return v.visit( this ); } 368 EnumPosType( const EnumInstType * instance ): instance(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) {} 369 371 370 private: 371 EnumPosType * clone() const override { return new EnumPosType{ *this }; } 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 }; } 372 377 MUTATE_FRIEND 373 378 }; -
src/AST/Visitor.hpp
rd9bad51 raf746cc 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 PosType* ) = 0;121 virtual const ast::Type * visit( const ast::EnumAttrType * ) = 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
rd9bad51 raf746cc 46 46 void postvisit( ast::UnionInstType const * type ); 47 47 void postvisit( ast::EnumInstType const * type ); 48 void postvisit( ast::Enum PosType const * type );48 void postvisit( ast::EnumAttrType 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 PosType const * type ) {242 void GenType::postvisit( ast::EnumAttrType const * type ) { 243 243 postvisit( type->instance ); 244 244 } -
src/Common/CodeLocationTools.cpp
rd9bad51 raf746cc 188 188 macro(UnionInstType, Type) \ 189 189 macro(EnumInstType, Type) \ 190 macro(Enum PosType, Type) \190 macro(EnumAttrType, Type) \ 191 191 macro(TraitInstType, Type) \ 192 192 macro(TypeInstType, Type) \ -
src/GenPoly/Lvalue.cpp
rd9bad51 raf746cc 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::npos147 || param_1_as_obj->name.find( "labels_" ) != std::string::npos );148 }149 135 } 150 136 } … … 176 162 ast::ApplicationExpr const * expr ) { 177 163 178 if ( skip == SkipInProgress || !isIntrinsicReference( expr ) || isGeneratedInstrinct( expr )) {164 if ( skip == SkipInProgress || !isIntrinsicReference( expr ) ) { 179 165 return expr; 180 166 } -
src/ResolvExpr/CandidateFinder.cpp
rd9bad51 raf746cc 285 285 const CodeLocation & location, 286 286 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs & args, 287 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,287 std::vector< ArgPack > & results, std::size_t & genStart, const ResolveContext & context, 288 288 unsigned nTuples = 0 289 289 ) { … … 295 295 // ^^^ need to handle the case where a tuple has a default argument 296 296 if ( ! instantiateArgument( location, 297 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;297 type, nullptr, args, results, genStart, context, nTuples ) ) return false; 298 298 nTuples = 0; 299 299 } … … 510 510 511 511 // attempt to unify types 512 if ( unify( paramType, argType, env, need, have, open ) ) { 512 ast::ptr<ast::Type> common; 513 if ( unify( paramType, argType, env, need, have, open, common ) ) { 513 514 // add new result 514 results.emplace_back( 515 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 516 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 515 assert( common ); 516 // auto attrType = common.as<ast::EnumAttrType>(); 517 // if ( attrType && ( attrType->attr == ast::EnumAttribute::Value ) ) { 518 // auto callExpr = new ast::UntypedExpr( 519 // expr->location, new ast::NameExpr( expr->location, "valueE"), {expr} ); 520 // CandidateFinder finder( context, env ); 521 // finder.find( callExpr ); 522 // CandidateList winners = findMinCost( finder.candidates ); 523 // if (winners.size() != 1) { 524 // SemanticError( callExpr, "Ambiguous expression in valueE" ); 525 // } 526 // CandidateRef & choice = winners.front(); 527 // choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 528 529 // results.emplace_back( 530 // i, choice->expr, 531 // std::move( env ), std::move( need ), std::move( have ), std::move( open ), 532 // nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 533 // } else { 534 results.emplace_back( 535 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 536 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 537 //} 517 538 } 518 539 } … … 786 807 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>(); 787 808 if ( !instantiateArgument( location, 788 funcType->params[i], obj->init, args, results, genStart, symtab)) return;809 funcType->params[i], obj->init, args, results, genStart, context)) return; 789 810 } 790 811 goto endMatch; … … 796 817 // no default args for indirect calls 797 818 if ( !instantiateArgument( location, 798 param, nullptr, args, results, genStart, symtab) ) return;819 param, nullptr, args, results, genStart, context ) ) return; 799 820 } 800 821 … … 891 912 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) { 892 913 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 } 914 } else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) { 915 if ( enumInst->base->base ) { 916 CandidateFinder finder( context, tenv ); 917 auto location = aggrExpr->location; 918 auto callExpr = new ast::UntypedExpr( 919 location, new ast::NameExpr( location, "valueE" ), {aggrExpr} 920 ); 921 finder.find( callExpr ); 922 CandidateList winners = findMinCost( finder.candidates ); 923 if (winners.size() != 1) { 924 SemanticError( callExpr, "Ambiguous expression in valueE" ); 925 } 926 CandidateRef & choice = winners.front(); 927 // choice->cost.incSafe(); 928 candidates.emplace_back( std::move(choice) ); 929 } 930 951 931 } 952 932 } … … 1415 1395 ast::Expr * newExpr = data.combine( nameExpr->location, cost ); 1416 1396 1397 bool bentConversion = false; 1398 if ( auto inst = newExpr->result.as<ast::EnumInstType>() ) { 1399 if ( inst->base && inst->base->base ) { 1400 bentConversion = true; 1401 } 1402 } 1403 1417 1404 CandidateRef newCand = std::make_shared<Candidate>( 1418 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,1405 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, bentConversion? Cost::safe: Cost::zero, 1419 1406 cost ); 1420 1407 … … 1449 1436 auto cand = new Candidate(variableExpr, tenv); 1450 1437 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 Call1463 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::cerr1490 << "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 1438 } 1512 1439 … … 1840 1767 1841 1768 // unification run for side-effects 1842 bool canUnify = unify( toType, cand->expr->result, env, need, have, open ); 1769 ast::ptr<ast::Type> common; 1770 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, common ); 1843 1771 (void) canUnify; 1844 1772 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), … … 1865 1793 // ambiguous case, still output candidates to print in error message 1866 1794 if ( cand->cost == minExprCost && thisCost == minCastCost ) { 1867 CandidateRef newCand = std::make_shared<Candidate>( 1868 new ast::InitExpr{ 1869 initExpr->location, 1870 restructureCast( cand->expr, toType ), 1871 initAlt.designation }, 1872 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1873 // currently assertions are always resolved immediately so this should have no effect. 1874 // if this somehow changes in the future (e.g. delayed by indeterminate return type) 1875 // we may need to revisit the logic. 1876 inferParameters( newCand, matches ); 1877 } 1878 } 1795 auto commonAsEnumAttr = common.as<ast::EnumAttrType>(); 1796 if ( commonAsEnumAttr && commonAsEnumAttr->attr == ast::EnumAttribute::Value ) { 1797 1798 auto callExpr = new ast::UntypedExpr( 1799 cand->expr->location, new ast::NameExpr( cand->expr->location, "valueE"), {cand->expr} ); 1800 CandidateFinder finder( context, env ); 1801 finder.find( callExpr ); 1802 CandidateList winners = findMinCost( finder.candidates ); 1803 if (winners.size() != 1) { 1804 SemanticError( callExpr, "Ambiguous expression in valueE" ); 1805 } 1806 CandidateRef & choice = winners.front(); 1807 // assert( valueCall->result ); 1808 CandidateRef newCand = std::make_shared<Candidate>( 1809 new ast::InitExpr{ 1810 initExpr->location, 1811 // restructureCast( cand->expr, toType ), 1812 choice->expr, 1813 initAlt.designation }, 1814 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1815 inferParameters( newCand, matches ); 1816 } else { 1817 CandidateRef newCand = std::make_shared<Candidate>( 1818 new ast::InitExpr{ 1819 initExpr->location, 1820 restructureCast( cand->expr, toType ), 1821 initAlt.designation }, 1822 std::move(env), std::move( open ), std::move( need ), cand->cost + thisCost ); 1823 // currently assertions are always resolved immediately so this should have no effect. 1824 // if this somehow changes in the future (e.g. delayed by indeterminate return type) 1825 // we may need to revisit the logic. 1826 inferParameters( newCand, matches ); 1827 } 1828 } 1829 } 1879 1830 } 1880 1831 } … … 1901 1852 std::make_shared<Candidate>( 1902 1853 newExpr, copy( tenv ), ast::OpenVarSet{}, 1903 ast::AssertionSet{}, Cost:: zero, cost1854 ast::AssertionSet{}, Cost::safe, cost 1904 1855 ); 1905 1856 … … 2201 2152 } 2202 2153 2154 // get the valueE(...) ApplicationExpr that returns the enum value 2155 const ast::Expr * getValueEnumCall( 2156 const ast::Expr * expr, 2157 const ResolvExpr::ResolveContext & context, const ast::TypeEnvironment & env ) { 2158 auto callExpr = new ast::UntypedExpr( 2159 expr->location, new ast::NameExpr( expr->location, "valueE"), {expr} ); 2160 CandidateFinder finder( context, env ); 2161 finder.find( callExpr ); 2162 CandidateList winners = findMinCost( finder.candidates ); 2163 if (winners.size() != 1) { 2164 SemanticError( callExpr, "Ambiguous expression in valueE" ); 2165 } 2166 CandidateRef & choice = winners.front(); 2167 return choice->expr; 2168 // return std::move( choice->expr.get() ); 2169 } 2170 2203 2171 } // namespace ResolvExpr 2204 2172 -
src/ResolvExpr/CandidateFinder.hpp
rd9bad51 raf746cc 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 75 } // namespace ResolvExpr 73 76 -
src/ResolvExpr/CommonType.cc
rd9bad51 raf746cc 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 ) { 388 result = enumDecl->base.get(); 389 } else { 387 if ( !enumDecl->base ) { 390 388 ast::BasicType::Kind kind = commonTypes[ basic->kind ][ ast::BasicType::SignedInt ]; 391 389 if ( … … 398 396 } 399 397 } 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 } 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 } 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 enum431 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->base435 && unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen)) {436 result = type1;437 return true;438 }439 }440 return false;441 428 } 442 429 … … 607 594 result = pointer; 608 595 add_qualifiers( result, type2->qualifiers ); 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 } 596 } 597 } 598 599 void postvisit( const ast::ArrayType * arr ) {} 618 600 619 601 void postvisit( const ast::ReferenceType * ref ) { … … 659 641 } 660 642 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 } 643 void postvisit( const ast::FunctionType * func) {} 644 645 void postvisit( const ast::StructInstType * inst ) {} 646 647 void postvisit( const ast::UnionInstType * inst ) {} 672 648 673 649 void postvisit( const ast::EnumInstType * enumInst ) { 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 } 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 * ) {} 693 657 694 658 void postvisit( const ast::TraitInstType * ) {} … … 696 660 void postvisit( const ast::TypeInstType * ) {} 697 661 698 void postvisit( const ast::TupleType * tuple ) { 699 tryResolveWithTypedEnum( tuple ); 700 } 662 void postvisit( const ast::TupleType * tuple ) {} 701 663 702 664 void postvisit( const ast::VarArgsType * ) {} … … 715 677 } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) { 716 678 const ast::EnumDecl * enumDecl = enumInst->base; 717 if ( enumDecl->base ) { 718 if ( tryResolveWithTypedEnum( zero ) ) 719 add_qualifiers( result, zero->qualifiers ); 720 } else { 679 if ( !enumDecl->base ) { 721 680 if ( widen.second || zero->qualifiers <= type2->qualifiers ) { 722 681 result = type2; … … 738 697 ast::BasicType::SignedInt, one->qualifiers | type2->qualifiers }; 739 698 } else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( type2 ) ) { 740 const ast::EnumDecl * enumBase = enumInst->base; 741 if ( enumBase->base ) { 742 if ( tryResolveWithTypedEnum( one )) 743 add_qualifiers( result, one->qualifiers ); 744 } else { 699 const ast::EnumDecl * enumDecl = enumInst->base; 700 if ( !enumDecl->base ) { 745 701 if ( widen.second || one->qualifiers <= type2->qualifiers ) { 746 702 result = type2; -
src/ResolvExpr/ConversionCost.cc
rd9bad51 raf746cc 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 ) ) { 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) ) { 280 } else if ( dynamic_cast< const ast::EnumAttrType *>(dst) ) { 291 281 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) }; 292 282 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 } 293 288 } 294 289 } … … 366 361 } 367 362 368 void ConversionCost::postvisit( const ast::EnumInstType * ) { 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 } 369 386 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) }; 370 387 cost = costCalc( integer, dst, srcIsLvalue, symtab, env ); … … 374 391 } 375 392 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 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 } 392 422 } 393 423 … … 466 496 cost.incSafe( maxIntCost + 2 ); 467 497 // 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 } 468 503 } 469 504 } … … 483 518 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] ); 484 519 } 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 } 485 525 } 486 526 } -
src/ResolvExpr/ConversionCost.h
rd9bad51 raf746cc 72 72 void postvisit( const ast::ZeroType * zeroType ); 73 73 void postvisit( const ast::OneType * oneType ); 74 void postvisit( const ast::Enum PosType * posType );74 void postvisit( const ast::EnumAttrType * posType ); 75 75 private: 76 76 // refactor for code resue -
src/ResolvExpr/Unify.cc
rd9bad51 raf746cc 274 274 void previsit( const ast::Node * ) { visit_children = false; } 275 275 276 void postvisit( const ast::VoidType * ) { 277 result = dynamic_cast< const ast::VoidType * >( type2 ); 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 ; 278 280 } 279 281 … … 282 284 result = basic->kind == basic2->kind; 283 285 } 286 result = result || tryToUnifyWithEnumValue(basic, type2, tenv, need, have, open, noWiden()); 284 287 } 285 288 … … 290 293 noWiden()); 291 294 } 295 result = result || tryToUnifyWithEnumValue(pointer, type2, tenv, need, have, open, noWiden()); 292 296 } 293 297 … … 307 311 308 312 result = unifyExact( 309 array->base, array2->base, tenv, need, have, open, noWiden()); 313 array->base, array2->base, tenv, need, have, open, noWiden()) 314 || tryToUnifyWithEnumValue(array, type2, tenv, need, have, open, noWiden()); 310 315 } 311 316 … … 399 404 } 400 405 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 401 420 public: 402 421 void postvisit( const ast::FunctionType * func ) { … … 507 526 void postvisit( const ast::StructInstType * aggrType ) { 508 527 handleGenericRefType( aggrType, type2 ); 528 result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden()); 509 529 } 510 530 511 531 void postvisit( const ast::UnionInstType * aggrType ) { 512 532 handleGenericRefType( aggrType, type2 ); 533 result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden()); 513 534 } 514 535 515 536 void postvisit( const ast::EnumInstType * aggrType ) { 516 537 handleRefType( aggrType, type2 ); 517 } 518 519 void postvisit( const ast::EnumPosType * posType ) { 538 result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden()); 539 } 540 541 void postvisit( const ast::EnumAttrType * enumAttr ) { 520 542 // Lazy approach for now 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 } 543 if ( auto otherPos = dynamic_cast< const ast::EnumAttrType *>(type2) ) { 544 if ( enumAttr->match(otherPos) ) { 545 result = otherPos; 546 } 547 } 526 548 } 527 549 528 550 void postvisit( const ast::TraitInstType * aggrType ) { 529 551 handleRefType( aggrType, type2 ); 552 result = result || tryToUnifyWithEnumValue(aggrType, type2, tenv, need, have, open, noWiden()); 530 553 } 531 554 … … 536 559 this->result = otherInst; 537 560 } 561 result = result || tryToUnifyWithEnumValue(typeInst, type2, tenv, need, have, open, noWiden()); 538 562 } 539 563 … … 610 634 auto types2 = flatten( flat2 ); 611 635 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 ); 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()); 625 653 } 626 654 }; -
src/SymTab/Mangler.cc
rd9bad51 raf746cc 58 58 void postvisit( const ast::OneType * oneType ); 59 59 void postvisit( const ast::QualifiedType * qualType ); 60 61 void postvisit( const ast::EnumPosType * posType ); 60 void postvisit( const ast::EnumAttrType * posType ); 62 61 63 62 /// The result is the current constructed mangled name. … … 281 280 } 282 281 283 void Mangler::postvisit( const ast::EnumPosType * pos ) { 284 postvisit( pos->instance ); 285 mangleName += "_pos"; 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 286 298 } 287 299 -
src/Validate/Autogen.cpp
rd9bad51 raf746cc 196 196 197 197 bool shouldAutogen() const final { return true; } 198 void genAttrFuncForward();199 void genPosFunctions();200 198 private: 201 199 void genFuncBody( ast::FunctionDecl * decl ) final; 202 200 void genFieldCtors() final; 203 201 const ast::Decl * getDecl() const final { return decl; } 204 205 ast::FunctionDecl * genPosProto() const;206 ast::FunctionDecl * genLabelProto() const;207 ast::FunctionDecl * genValueProto() const;208 ast::FunctionDecl * genSuccProto() const;209 ast::FunctionDecl * genPredProto() const;210 211 ast::FunctionDecl * genSuccPosProto() const;212 ast::FunctionDecl * genPredPosProto() const;213 214 ast::FunctionDecl * genSuccPredFunc( bool succ );215 // ast::FunctionDecl * genPredFunc();216 202 }; 217 203 … … 256 242 enumInst.base = enumDecl; 257 243 EnumFuncGenerator gen( enumDecl, &enumInst, functionNesting ); 258 if ( enumDecl->base ) {259 gen.genAttrFuncForward();260 gen.genPosFunctions();261 }262 244 gen.generateAndAppendFunctions( declsToAddAfter ); 263 245 } … … 418 400 } 419 401 420 /// Use the current type T to create `void ?{}(T & _dst)`.402 /// Use the current type T to create `void ^?{}(T & _dst)`. 421 403 ast::FunctionDecl * FuncGenerator::genDtorProto() const { 422 404 // The destructor must be mutex on a concurrent type. … … 777 759 } 778 760 779 ast::FunctionDecl * EnumFuncGenerator::genPosProto() const {780 return genProto( "posE",781 { new ast::ObjectDecl( getLocation(), "_i",782 new ast::EnumInstType( decl ) )},783 { new ast::ObjectDecl( getLocation(), "_ret",784 new ast::BasicType{ ast::BasicType::UnsignedInt } )} );785 }786 787 ast::FunctionDecl * EnumFuncGenerator::genLabelProto() const {788 return genProto( "labelE",789 { new ast::ObjectDecl( getLocation(), "_i",790 new ast::EnumInstType( decl ) ) },791 { new ast::ObjectDecl( getLocation(), "_ret",792 new ast::PointerType( new ast::BasicType{ ast::BasicType::Char } ) ) } );793 }794 795 ast::FunctionDecl * EnumFuncGenerator::genValueProto() const {796 return genProto( "valueE",797 { new ast::ObjectDecl( getLocation(), "_i", new ast::EnumInstType( decl ) )},798 { new ast::ObjectDecl( getLocation(), "_ret", ast::deepCopy( decl->base ) ) } );799 }800 801 ast::FunctionDecl * EnumFuncGenerator::genSuccProto() const {802 return genProto( "succ",803 { new ast::ObjectDecl( getLocation(), "_i", new ast::EnumInstType( decl ) )},804 { new ast::ObjectDecl( getLocation(), "_ret", new ast::EnumInstType( decl ))} );805 }806 807 ast::FunctionDecl * EnumFuncGenerator::genPredProto() const {808 return genProto( "pred",809 { new ast::ObjectDecl( getLocation(), "_i", new ast::EnumInstType( decl ))},810 { new ast::ObjectDecl( getLocation(), "_ret", new ast::EnumInstType( decl ))} );811 }812 813 ast::FunctionDecl * EnumFuncGenerator::genSuccPosProto() const {814 return genProto( "_successor_",815 { new ast::ObjectDecl( getLocation(), "_i",816 new ast::EnumPosType( new ast::EnumInstType( decl ) ) )},817 {818 new ast::ObjectDecl( getLocation(), "_ret",819 new ast::EnumPosType( new ast::EnumInstType( decl ) ) )820 } );821 }822 823 ast::FunctionDecl * EnumFuncGenerator::genPredPosProto() const {824 return genProto( "_predessor_",825 { new ast::ObjectDecl( getLocation(), "_i",826 new ast::EnumPosType( new ast::EnumInstType( decl ) ) )},827 {828 new ast::ObjectDecl( getLocation(), "_ret",829 new ast::EnumPosType( new ast::EnumInstType( decl ) ) )830 } );831 }832 833 ast::FunctionDecl * EnumFuncGenerator::genSuccPredFunc( bool succ ) {834 ast::FunctionDecl * decl = succ? genSuccPosProto(): genPredPosProto();835 produceForwardDecl( decl );836 837 const CodeLocation& location = getLocation();838 839 auto & params = decl->params;840 assert( params.size() == 1 );841 auto param = params.front().strict_as<ast::ObjectDecl>();842 843 auto newReturn = new ast::ObjectDecl( location, "_returns",844 new ast::BasicType{ ast::BasicType::SignedInt} );845 846 847 ast::UntypedExpr * addOneExpr = new ast::UntypedExpr( location,848 new ast::NameExpr( location, succ? "?+?": "?-?" )849 );850 addOneExpr->args.push_back(851 new ast::CastExpr( location,852 new ast::VariableExpr( location, param ),853 new ast::BasicType{ ast::BasicType::SignedInt }854 )855 );856 addOneExpr->args.push_back(857 ast::ConstantExpr::from_int( location, 1 )858 );859 860 ast::UntypedExpr * assignExpr = new ast::UntypedExpr( location,861 new ast::NameExpr( location, "?=?" )862 );863 assignExpr->args.push_back(864 new ast::VariableExpr( location, newReturn )865 );866 assignExpr->args.push_back(867 addOneExpr868 );869 870 decl->stmts = new ast::CompoundStmt( location,871 {872 new ast::DeclStmt( location, newReturn ),873 new ast::ExprStmt( location, assignExpr ),874 new ast::ReturnStmt( location,875 new ast::VariableExpr( location, newReturn ))876 } );877 878 return decl;879 }880 881 void EnumFuncGenerator::genAttrFuncForward() {882 if ( decl->base ) {883 ast::FunctionDecl *(EnumFuncGenerator::*attrProtos[5])() const = {884 &EnumFuncGenerator::genPosProto, &EnumFuncGenerator::genLabelProto,885 &EnumFuncGenerator::genValueProto, &EnumFuncGenerator::genSuccProto,886 &EnumFuncGenerator::genPredProto887 // ,&EnumFuncGenerator::genSuccPosProto,888 // &EnumFuncGenerator::genPredPosProto889 };890 for ( auto & generator : attrProtos ) {891 produceForwardDecl( (this->*generator)() );892 }893 }894 }895 896 void EnumFuncGenerator::genPosFunctions() {897 if ( decl->base ) {898 ast::FunctionDecl * succ = genSuccPredFunc( true );899 ast::FunctionDecl * pred = genSuccPredFunc( false );900 produceDecl( succ );901 produceDecl( pred );902 }903 904 }905 906 761 void TypeFuncGenerator::genFieldCtors() { 907 762 // Opaque types do not have field constructors. -
src/Validate/ReplacePseudoFunc.cpp
rd9bad51 raf746cc 16 16 17 17 namespace { 18 19 std::set<std::string> queryLabels;20 std::set<std::string> queryValues;21 22 struct ReplaceEnumInstWithPos final : public ast::WithShortCircuiting {23 const ast::ObjectDecl* postvisit(const ast::ObjectDecl* decl) {24 auto enumInst = decl->type.strict_as<ast::EnumInstType>();25 auto enumPos = new ast::EnumPosType(enumInst);26 auto ret = ast::mutate_field(decl, &ast::ObjectDecl::type, enumPos);27 ret = ast::mutate_field(ret, &ast::ObjectDecl::mangleName,28 Mangle::mangle(ret));29 return ret;30 }31 };32 33 const inline std::string getValueArrayName(std::string enumName) {34 return "values_" + enumName;35 }36 37 // struct AutoInit {38 // ast::EnumDecl const* postvisit( const ast::EnumDecl* expr );39 // };40 41 struct WrapEnumValueExpr final : public ast::WithShortCircuiting,42 public ast::WithSymbolTable,43 public ast::WithConstTranslationUnit {44 void previsit(const ast::DeclStmt* expr);45 void previsit(const ast::ApplicationExpr* expr);46 void previsit(const ast::CastExpr* expr);47 void previsit(const ast::VariableExpr*) { visit_children = false; }48 49 ast::Expr const* postvisit(const ast::VariableExpr* expr);50 };51 52 struct FindGenEnumArray final : public ast::WithShortCircuiting {53 void previsit(const ast::ApplicationExpr* enumDecl);54 };55 56 struct PseudoFuncGenerateRoutine final : public ast::WithDeclsToAdd<>,57 public ast::WithSymbolTable,58 public ast::WithShortCircuiting,59 public ast::WithConstTranslationUnit {60 void previsit(const ast::EnumDecl* enumDecl);61 };62 63 struct ReplacePseudoFuncCore : public ast::WithShortCircuiting,64 public ast::WithSymbolTable,65 public ast::WithConstTranslationUnit {66 ast::Expr const* postvisit(ast::ApplicationExpr const* decl);67 };68 69 // ast::EnumDecl const * AutoInit::postvisit( const ast::EnumDecl * expr ) {70 // for ( size_t i = 0; i < expr->members.size(); i++ ) {71 // auto mem = expr->members[i].as<ast::ObjectDecl>();72 // assert( mem );73 // if ( mem->init )74 // }75 // return expr;76 // }77 78 void WrapEnumValueExpr::previsit(const ast::ApplicationExpr* expr) {79 auto varExpr = expr->func.as<ast::VariableExpr>();80 auto fname = ast::getFunctionName(expr);81 if (!varExpr || varExpr->var->linkage == ast::Linkage::Intrinsic) {82 if (fname == "?{}" || fname == "?=?") visit_children = false;83 }84 85 if (fname == "labelE" || fname == "valueE" || fname == "posE" ||86 fname == "pred" || fname == "succ") {87 visit_children = false;88 }89 }90 91 void WrapEnumValueExpr::previsit(const ast::DeclStmt*) {92 visit_children = false;93 }94 95 void WrapEnumValueExpr::previsit(const ast::CastExpr* expr) {96 if (expr->result && expr->result.as<ast::ReferenceType>()) {97 visit_children = false;98 }99 }100 101 ast::Expr const* WrapEnumValueExpr::postvisit(const ast::VariableExpr* expr) {102 if (!expr->result) {103 return expr;104 }105 if (auto enumInst = expr->result.as<ast::EnumInstType>()) {106 if (enumInst->base && enumInst->base->base) {107 auto untyped = new ast::UntypedExpr(108 expr->location, new ast::NameExpr(expr->location, "valueE"),109 {std::move(expr)});110 ResolvExpr::ResolveContext context{symtab, transUnit().global};111 auto result = ResolvExpr::findVoidExpression(untyped, context);112 ast::ptr<ast::ApplicationExpr> ret =113 result.strict_as<ast::ApplicationExpr>();114 return ast::deepCopy(ret);115 }116 }117 return expr;118 }119 120 void FindGenEnumArray::previsit(const ast::ApplicationExpr* expr) {121 auto fname = ast::getFunctionName(expr);122 if (fname == "labelE" || fname == "valueE") {123 if (expr->args.size() != 1) {124 SemanticError(expr, "Position Expression only take one parameter");125 }126 const ast::VariableExpr* arg =127 expr->args.front().as<const ast::VariableExpr>();128 if (!arg) {129 SemanticError(expr, "Unimplement Pseudo Function Cases");130 }131 const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();132 const std::string referredName = argAsVar->name;133 const ast::EnumInstType* argType =134 argAsVar->type.as<const ast::EnumInstType>();135 if (!argType) {136 SemanticError(137 argAsVar,138 "Position can only be used on an enumeration instance");139 }140 ast::ptr<ast::EnumDecl> base = argType->base;141 assert(base);142 if (fname == "labelE") queryLabels.insert(base->name);143 if (fname == "valueE") queryValues.insert(base->name);144 }145 }146 147 const ast::Init* getAutoInit(const CodeLocation& location,148 const ast::Type* type,149 ResolvExpr::ResolveContext context,150 const ast::Init* prev) {151 if (auto prevInit = dynamic_cast<const ast::SingleInit*>(prev)) {152 auto prevInitExpr = prevInit->value;153 if (auto constInit = prevInitExpr.as<ast::ConstantExpr>()) {154 // Assume no string literal for now155 return new ast::SingleInit(156 location, ast::ConstantExpr::from_int(157 location, constInit->intValue() + 1));158 } else {159 auto untypedThisInit = new ast::UntypedExpr(160 location, new ast::NameExpr(location, "?++"), {prevInitExpr});161 auto typedInit = ResolvExpr::findSingleExpression(untypedThisInit,162 type, context);163 return new ast::SingleInit(location, typedInit);164 }165 }166 SemanticError(prev, "Auto Init a List is not implemented");167 return prev;168 }169 170 void PseudoFuncGenerateRoutine::previsit(const ast::EnumDecl* enumDecl) {171 visit_children = false;172 const CodeLocation& location = enumDecl->location;173 if (enumDecl->members.size() == 0 || !enumDecl->base) return;174 175 std::vector<ast::ptr<ast::Init>> inits;176 std::vector<ast::ptr<ast::Init>> labels;177 auto type = enumDecl->base;178 179 for (size_t i = 0; i < enumDecl->members.size(); i++) {180 ast::ptr<ast::Decl> mem = enumDecl->members.at(i);181 auto memAsObjectDecl = mem.as<ast::ObjectDecl>();182 assert(memAsObjectDecl);183 if (memAsObjectDecl->init) {184 inits.emplace_back(memAsObjectDecl->init);185 } else {186 const CodeLocation& location = mem->location;187 if (i == 0) {188 inits.emplace_back(new ast::SingleInit(189 location, ast::ConstantExpr::from_int(mem->location, 0)));190 } else {191 inits.emplace_back(getAutoInit(192 location, enumDecl->base,193 ResolvExpr::ResolveContext{symtab, transUnit().global},194 inits.at(i - 1).as<ast::SingleInit>()));195 }196 }197 labels.emplace_back(new ast::SingleInit(198 location, ast::ConstantExpr::from_string(location, mem->name)));199 }200 if (queryValues.count(enumDecl->name)) {201 auto init = new ast::ListInit(location, std::move(inits));202 const ast::ArrayType* arrT = new ast::ArrayType(203 enumDecl->base,204 ast::ConstantExpr::from_int(location, enumDecl->members.size()),205 ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim);206 ast::ObjectDecl* values = new ast::ObjectDecl(207 location, "values_" + enumDecl->name, arrT, init,208 ast::Storage::Static, ast::Linkage::AutoGen);209 symtab.addId(values);210 values->mangleName = Mangle::mangle(values);211 declsToAddAfter.push_back(values);212 }213 if (queryLabels.count(enumDecl->name)) {214 auto label_strings = new ast::ListInit(location, std::move(labels));215 auto labels = new ast::ObjectDecl(216 location, "labels_" + enumDecl->name,217 new ast::ArrayType(218 new ast::PointerType(new ast::BasicType{ast::BasicType::Char}),219 ast::ConstantExpr::from_int(location, enumDecl->members.size()),220 ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim),221 label_strings, ast::Storage::Static, ast::Linkage::AutoGen);222 symtab.addId(labels);223 labels->mangleName = Mangle::mangle(labels);224 declsToAddAfter.push_back(labels);225 }226 }227 228 ast::ApplicationExpr const* resolveAttributeFunctions(229 const CodeLocation location, ResolvExpr::ResolveContext context,230 const ast::VariableExpr* arg, const ast::EnumDecl* base,231 const std::string& name) {232 ast::Expr* toResolve = new ast::NameExpr(location, name + base->name);233 // Find the request arrary234 auto arr = ResolvExpr::findVoidExpression(toResolve, context);235 assert(arr.get());236 auto arrAsVar = arr.strict_as<ast::VariableExpr>();237 // change EnumInstType to EnumPosType to avoid recursive resolution238 auto argAsDecl = arg->var.as<ast::ObjectDecl>();239 if (argAsDecl->type.as<ast::EnumInstType>()) {240 ast::Pass<ReplaceEnumInstWithPos> replacer;241 auto rep = argAsDecl->accept(replacer);242 auto mutatedArg = ast::mutate_field(arg, &ast::VariableExpr::var, rep);243 mutatedArg = ast::mutate_field(mutatedArg, &ast::VariableExpr::result,244 mutatedArg->var->get_type());245 auto untyped =246 new ast::UntypedExpr(location, new ast::NameExpr(location, "?[?]"),247 {std::move(arrAsVar), mutatedArg});248 auto typedResult = ResolvExpr::findVoidExpression(untyped, context);249 ast::ptr<ast::ApplicationExpr> ret =250 typedResult.strict_as<ast::ApplicationExpr>();251 return ast::deepCopy(ret);252 } else {253 auto untyped =254 new ast::UntypedExpr(location, new ast::NameExpr(location, "?[?]"),255 {std::move(arrAsVar), arg});256 auto typedResult = ResolvExpr::findVoidExpression(untyped, context);257 258 ast::ptr<ast::ApplicationExpr> ret =259 typedResult.strict_as<ast::ApplicationExpr>();260 return ast::deepCopy(ret);261 }262 }263 264 ast::Expr const* ReplacePseudoFuncCore::postvisit(265 ast::ApplicationExpr const* expr) {266 auto fname = ast::getFunctionName(expr);267 auto location = expr->location;268 if (fname == "posE" || fname == "valueE" || fname == "labelE") {269 if (expr->args.size() != 1) {270 SemanticError(expr,271 "Pseudo Enum Expression only take one parameter");272 }273 ast::ptr<ast::VariableExpr> arg =274 expr->args.front().as<const ast::VariableExpr>();275 if (!arg) {276 SemanticError(expr, "Unimplement Pseudo Function Cases");277 }278 const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();279 const std::string referredName = argAsVar->name;280 281 if (const ast::EnumInstType* argTypeAsEnumInst =282 argAsVar->type.as<const ast::EnumInstType>()) {283 const ast::EnumDecl* base = argTypeAsEnumInst->base;284 ResolvExpr::ResolveContext context{symtab, transUnit().global};285 // If resolvable as constant286 for (size_t i = 0; i < base->members.size(); i++) {287 if (base->members[i]->name == referredName) {288 if (fname == "posE")289 return ast::ConstantExpr::from_int(expr->location, i);290 else if (fname == "labelE")291 return ast::ConstantExpr::from_string(expr->location,292 referredName);293 else {294 return resolveAttributeFunctions(295 location, context, arg.get(), base, "values_");296 }297 }298 }299 300 if (fname == "labelE") {301 if (auto labelExpr = resolveAttributeFunctions(302 location, context, arg.get(), base, "labels_")) {303 return labelExpr;304 }305 } else if (fname == "valueE") {306 if (auto valueExpr = resolveAttributeFunctions(307 location, context, arg.get(), base, "values_")) {308 return valueExpr;309 }310 } else { // it is position; replace itself311 return std::move(arg.get());312 }313 } else if (const ast::EnumPosType* argTypeAsPos =314 argAsVar->type.as<const ast::EnumPosType>()) {315 const ast::EnumDecl* base = argTypeAsPos->instance->base;316 ResolvExpr::ResolveContext context{symtab, transUnit().global};317 if (fname == "labelE") {318 if (auto labelExpr = resolveAttributeFunctions(319 location, context, arg.get(), base, "labels_")) {320 return labelExpr;321 }322 } else if (fname == "valueE") {323 if (auto valueExpr = resolveAttributeFunctions(324 location, context, arg.get(), base, "values_")) {325 return valueExpr;326 }327 } else { // it is position; replace itself328 return std::move(arg.get());329 }330 } else {331 SemanticError(argAsVar,332 "Pseudo Enum Expression can only be used on an "333 "enumeration instance");334 }335 }336 return expr;337 }338 18 339 19 ast::ptr<ast::Expr> reduceCastExpr(ast::ptr<ast::Expr> expr) { … … 357 37 if (auto enumInst = 358 38 argAsDecl->type.as<ast::EnumInstType>()) { 359 auto castTo = new ast::EnumPosType(enumInst); 39 auto castTo = new ast::EnumAttrType( 40 enumInst, ast::EnumAttribute::Posn); 360 41 auto castExpr = 361 42 new ast::CastExpr(param->location, param, castTo); … … 375 56 return ast::deepCopy(ret); 376 57 } else if (auto posType = 377 argAsDecl->type.as<ast::EnumPosType>()) { 378 // Very nasty fix. Must be revisit 379 if (auto paramAsVar = param.as<ast::VariableExpr>()) { 380 if (paramAsVar->result.as<ast::EnumInstType>()) { 381 auto paramToUse = ast::mutate_field( 382 paramAsVar, &ast::VariableExpr::result, 383 posType); 384 auto untyped = new ast::UntypedExpr( 385 expr->location, 386 new ast::NameExpr(location, 387 fname == "succ" 388 ? "_successor_" 389 : "_predessor_"), 390 {paramToUse}); 391 ResolvExpr::ResolveContext context{ 392 symtab, transUnit().global}; 393 auto typedResult = 394 ResolvExpr::findVoidExpression(untyped, 395 context); 396 ast::ptr<ast::ApplicationExpr> ret = 397 typedResult 398 .strict_as<ast::ApplicationExpr>(); 399 return ast::deepCopy(ret); 400 } 401 } 402 auto untyped = new ast::UntypedExpr( 403 expr->location, 404 new ast::NameExpr(location, fname == "succ" 405 ? "_successor_" 406 : "_predessor_"), 407 {param}); 408 ResolvExpr::ResolveContext context{symtab, 409 transUnit().global}; 410 auto typedResult = 411 ResolvExpr::findVoidExpression(untyped, context); 412 ast::ptr<ast::ApplicationExpr> ret = 413 typedResult.strict_as<ast::ApplicationExpr>(); 414 return ast::deepCopy(ret); 58 argAsDecl->type.as<ast::EnumAttrType>()) { 59 std::cerr << "PseudoFunc: succ/pred should not be applied on EnumAttrType directly" << std::endl; 415 60 } 416 61 } … … 424 69 425 70 void replacePseudoFunc(ast::TranslationUnit& translationUnit) { 426 ast::Pass<WrapEnumValueExpr>::run(translationUnit);427 ast::Pass<FindGenEnumArray>::run(translationUnit);428 429 ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit);430 ast::Pass<ReplacePseudoFuncCore>::run(translationUnit);431 432 71 ast::Pass<ReplaceSuccAndPred>::run(translationUnit); 433 72 } -
src/Validate/module.mk
rd9bad51 raf746cc 54 54 Validate/VerifyCtorDtorAssign.hpp \ 55 55 Validate/ReplacePseudoFunc.cpp \ 56 Validate/ReplacePseudoFunc.hpp 56 Validate/ReplacePseudoFunc.hpp \ 57 Validate/ImplementEnumFunc.cpp \ 58 Validate/ImplementEnumFunc.hpp 57 59 58 60 SRCDEMANGLE += $(SRC_VALIDATE) -
src/main.cc
rd9bad51 raf746cc 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() ); 385 PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() ); // Here 386 386 PASS( "Erase With", ResolvExpr::eraseWith, transUnit ); 387 387
Note:
See TracChangeset
for help on using the changeset viewer.