Changeset ef1da0e2
- Timestamp:
- Sep 20, 2022, 6:34:55 PM (2 years ago)
- Branches:
- ADT, ast-experimental, master, pthread-emulation
- Children:
- 79ae13d, a065f1f
- Parents:
- 8f1e035
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/monitor.hfa
r8f1e035 ref1da0e2 60 60 void ^?{}( monitor_dtor_guard_t & this ); 61 61 62 /* 62 63 static inline forall( T & | sized(T) | { void ^?{}( T & mutex ); } ) 63 64 void delete( T * th ) { … … 65 66 free( th ); 66 67 } 68 */ 67 69 68 70 static inline forall( T & | sized(T) | { void ^?{}( T & mutex ); } ) -
src/AST/Print.cpp
r8f1e035 ref1da0e2 90 90 91 91 static constexpr auto Qualifiers = make_array<const char*>( 92 "const", "restrict", "volatile", " lvalue", "mutex", "_Atomic"92 "const", "restrict", "volatile", "mutex", "_Atomic" 93 93 ); 94 94 }; … … 1624 1624 constexpr array<const char*, 3> Printer::Names::FuncSpecifiers; 1625 1625 constexpr array<const char*, 6> Printer::Names::StorageClasses; 1626 constexpr array<const char*, 6> Printer::Names::Qualifiers;1626 constexpr array<const char*, 5> Printer::Names::Qualifiers; 1627 1627 } -
src/AST/TypeEnvironment.hpp
r8f1e035 ref1da0e2 56 56 struct AssertCompare { 57 57 bool operator()( const VariableExpr * d1, const VariableExpr * d2 ) const { 58 auto kind1 = ast::SymbolTable::getSpecialFunctionKind(d1->var->name); 59 auto kind2 = ast::SymbolTable::getSpecialFunctionKind(d2->var->name); 60 // heuristics optimization: force special functions to go last 61 if (kind1 > kind2) return true; 62 else if (kind1 < kind2) return false; 63 58 64 int cmp = d1->var->name.compare( d2->var->name ); 59 65 return cmp < 0 || ( cmp == 0 && d1->result < d2->result ); -
src/ResolvExpr/CommonType.cc
r8f1e035 ref1da0e2 28 28 #include "Unify.h" // for unifyExact, WidenMode 29 29 #include "typeops.h" // for isFtype 30 #include "Tuples/Tuples.h" 30 31 31 32 // #define DEBUG … … 675 676 ast::TypeEnvironment & tenv; 676 677 const ast::OpenVarSet & open; 678 ast::AssertionSet & need; 679 ast::AssertionSet & have; 677 680 public: 678 681 static size_t traceId; … … 681 684 CommonType_new( 682 685 const ast::Type * t2, WidenMode w, const ast::SymbolTable & st, 683 ast::TypeEnvironment & env, const ast::OpenVarSet & o ) 684 : type2( t2 ), widen( w ), symtab( st ), tenv( env ), open( o ), result() {} 686 ast::TypeEnvironment & env, const ast::OpenVarSet & o, 687 ast::AssertionSet & need, ast::AssertionSet & have ) 688 : type2( t2 ), widen( w ), symtab( st ), tenv( env ), open( o ), need (need), have (have) ,result() {} 685 689 686 690 void previsit( const ast::Node * ) { visit_children = false; } … … 753 757 bool tryResolveWithTypedEnum( const ast::Type * type1 ) { 754 758 if (auto enumInst = dynamic_cast<const ast::EnumInstType *> (type2) ) { 755 ast::AssertionSet have, need; // unused756 759 ast::OpenVarSet newOpen{ open }; 757 760 if (enumInst->base->base … … 792 795 reset_qualifiers( t2 ); 793 796 794 ast::AssertionSet have, need;795 797 ast::OpenVarSet newOpen{ open }; 796 798 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) { … … 803 805 } 804 806 } 807 else if ( isFtype (t1) && isFtype (t2) ) { 808 auto f1 = t1.as<ast::FunctionType>(); 809 if (!f1) return; 810 auto f2 = t2.strict_as<ast::FunctionType>(); 811 812 assertf(f1->returns.size() <= 1, "Function return should not be a list"); 813 assertf(f2->returns.size() <= 1, "Function return should not be a list"); 814 815 if ( 816 ( f1->params.size() != f2->params.size() || f1->returns.size() != f2->returns.size() ) 817 && ! f1->isTtype() 818 && ! f2->isTtype() 819 ) return; 820 821 auto params1 = flattenList( f1->params, tenv ); 822 auto params2 = flattenList( f2->params, tenv ); 823 824 auto crnt1 = params1.begin(); 825 auto crnt2 = params2.begin(); 826 auto end1 = params1.end(); 827 auto end2 = params2.end(); 828 829 while (crnt1 != end1 && crnt2 != end2 ) { 830 const ast::Type * arg1 = *crnt1; 831 const ast::Type * arg2 = *crnt2; 832 833 bool isTuple1 = Tuples::isTtype( t1 ); 834 bool isTuple2 = Tuples::isTtype( t2 ); 835 836 // assumes here that ttype *must* be last parameter 837 if ( isTuple1 && ! isTuple2 ) { 838 // combine remainder of list2, then unify 839 if (unifyExact( 840 arg1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open, 841 noWiden(), symtab )) { 842 break; 843 844 } 845 else return; 846 } else if ( ! isTuple1 && isTuple2 ) { 847 // combine remainder of list1, then unify 848 if (unifyExact( 849 tupleFromTypes( crnt1, end1 ), arg2, tenv, need, have, open, 850 noWiden(), symtab )) { 851 break; 852 853 } 854 else return; 855 } 856 857 // allow qualifiers of pointer and reference base to become more specific 858 if (auto ref1 = dynamic_cast<const ast::ReferenceType *> (arg1)) { 859 if (auto ref2 = dynamic_cast<const ast::ReferenceType *> (arg2)) { 860 ast::ptr<ast::Type> base1 = ref1->base; 861 ast::ptr<ast::Type> base2 = ref2->base; 862 863 // xxx - assume LHS is always the target type 864 865 if ( ! ((widen.second && ref2->qualifiers.is_mutex) 866 || (ref1->qualifiers.is_mutex == ref2->qualifiers.is_mutex ))) return; 867 868 if ( (widen.second && base1->qualifiers <= base2->qualifiers ) || (base2->qualifiers == base1->qualifiers) ) { 869 870 reset_qualifiers(base1); 871 reset_qualifiers(base2); 872 873 if ( ! unifyExact( 874 base1, base2, tenv, need, have, open, noWiden(), symtab ) 875 ) return; 876 } 877 } 878 else return; 879 } 880 else if (auto ptr1 = dynamic_cast<const ast::PointerType *> (arg1)) { 881 if (auto ptr2 = dynamic_cast<const ast::PointerType *> (arg2)) { 882 ast::ptr<ast::Type> base1 = ptr1->base; 883 ast::ptr<ast::Type> base2 = ptr2->base; 884 885 // xxx - assume LHS is always the target type 886 // a function accepting const can always be called by non-const arg 887 888 if ( (widen.second && base1->qualifiers <= base2->qualifiers ) || (base2->qualifiers == base1->qualifiers) ) { 889 890 reset_qualifiers(base1); 891 reset_qualifiers(base2); 892 893 if ( ! unifyExact( 894 base1, base2, tenv, need, have, open, noWiden(), symtab ) 895 ) return; 896 } 897 } 898 else return; 899 900 } 901 else if (! unifyExact( 902 arg1, arg2, tenv, need, have, open, noWiden(), symtab )) return; 903 904 ++crnt1; ++crnt2; 905 } 906 if ( crnt1 != end1 ) { 907 // try unifying empty tuple with ttype 908 const ast::Type * t1 = *crnt1; 909 if (! Tuples::isTtype( t1 ) ) return; 910 if (! unifyExact( 911 t1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open, 912 noWiden(), symtab )) return; 913 } else if ( crnt2 != end2 ) { 914 // try unifying empty tuple with ttype 915 const ast::Type * t2 = *crnt2; 916 if (! Tuples::isTtype( t2 ) ) return; 917 if (! unifyExact( 918 tupleFromTypes( crnt1, end1 ), t2, tenv, need, have, open, 919 noWiden(), symtab )) return; 920 } 921 if ((f1->returns.size() == 0 && f2->returns.size() == 0) 922 || (f1->returns.size() == 1 && f2->returns.size() == 1 && unifyExact(f1->returns[0], f2->returns[0], tenv, need, have, open, noWiden(), symtab))) { 923 result = pointer; 924 925 for (auto & assn : f1->assertions) { 926 auto i = need.find(assn); 927 if (i != need.end()) i->second.isUsed = true; 928 auto j = have.find(assn); 929 if (j != have.end()) j->second.isUsed = true; 930 } 931 932 for (auto & assn : f2->assertions) { 933 auto i = need.find(assn); 934 if (i != need.end()) i->second.isUsed = true; 935 auto j = have.find(assn); 936 if (j != have.end()) j->second.isUsed = true; 937 } 938 939 } 940 } // if ftype 941 805 942 } 806 943 } else if ( widen.second && dynamic_cast< const ast::ZeroType * >( type2 ) ) { … … 839 976 reset_qualifiers( t2 ); 840 977 841 ast::AssertionSet have, need;842 978 ast::OpenVarSet newOpen{ open }; 843 979 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) { … … 857 993 // xxx - does unifying a ref with typed enumInst makes sense? 858 994 if (!dynamic_cast<const ast::EnumInstType *>(type2)) 859 result = commonType( type2, ref, widen, symtab, tenv, open);995 result = commonType( type2, ref, tenv, need, have, open, widen, symtab ); 860 996 } 861 997 } … … 877 1013 // xxx - is this already handled by unify? 878 1014 if (!dynamic_cast<const ast::EnumInstType *>(type2)) 879 result = commonType( type2, enumInst, widen, symtab, tenv, open);1015 result = commonType( type2, enumInst, tenv, need, have, open, widen, symtab); 880 1016 } 881 1017 … … 895 1031 reset_qualifiers( t2 ); 896 1032 897 ast::AssertionSet have, need;898 1033 ast::OpenVarSet newOpen{ open }; 899 1034 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) { … … 999 1134 ast::ptr< ast::Type > commonType( 1000 1135 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, 1001 WidenMode widen, const ast::SymbolTable & symtab, ast::TypeEnvironment & env,1002 const ast::OpenVarSet & open 1136 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1137 const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab 1003 1138 ) { 1004 1139 unsigned depth1 = type1->referenceDepth(); … … 1036 1171 } 1037 1172 // otherwise both are reference types of the same depth and this is handled by the visitor 1038 ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open };1173 ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open, need, have }; 1039 1174 type1->accept( visitor ); 1040 1175 ast::ptr< ast::Type > result = visitor.core.result; … … 1047 1182 if ( type->base ) { 1048 1183 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers; 1049 ast::AssertionSet have, need;1050 1184 ast::OpenVarSet newOpen{ open }; 1051 1185 -
src/ResolvExpr/ConversionCost.cc
r8f1e035 ref1da0e2 22 22 #include "ResolvExpr/Cost.h" // for Cost 23 23 #include "ResolvExpr/TypeEnvironment.h" // for EqvClass, TypeEnvironment 24 #include "ResolvExpr/Unify.h" 24 25 #include "SymTab/Indexer.h" // for Indexer 25 26 #include "SynTree/Declaration.h" // for TypeDecl, NamedTypeDecl 26 27 #include "SynTree/Type.h" // for Type, BasicType, TypeInstType 27 28 #include "typeops.h" // for typesCompatibleIgnoreQualifiers 29 28 30 29 31 namespace ResolvExpr { … … 655 657 cost = Cost::safe; 656 658 } 657 } else { 659 } 660 /* 661 else if ( const ast::FunctionType * dstFunc = dstAsPtr->base.as<ast::FunctionType>()) { 662 if (const ast::FunctionType * srcFunc = pointerType->base.as<ast::FunctionType>()) { 663 if (dstFunc->params.empty() && dstFunc->isVarArgs ) { 664 cost = Cost::unsafe; // assign any function to variadic fptr 665 } 666 } 667 else { 668 ast::AssertionSet need, have; // unused 669 ast::OpenVarSet open; 670 env.extractOpenVars(open); 671 ast::TypeEnvironment tenv = env; 672 if ( unify(dstAsPtr->base, pointerType->base, tenv, need, have, open, symtab) ) { 673 cost = Cost::safe; 674 } 675 } 676 // else infinity 677 } 678 */ 679 else { 658 680 int assignResult = ptrsAssignable( pointerType->base, dstAsPtr->base, env ); 659 681 if ( 0 < assignResult && tq1 <= tq2 ) { -
src/ResolvExpr/SatisfyAssertions.cpp
r8f1e035 ref1da0e2 36 36 #include "AST/SymbolTable.hpp" 37 37 #include "AST/TypeEnvironment.hpp" 38 #include "FindOpenVars.h" 38 39 #include "Common/FilterCombos.h" 39 40 #include "Common/Indenter.h" … … 161 162 162 163 /// Satisfy a single assertion 163 bool satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat 164 bool satisfyAssertion( ast::AssertionList::value_type & assn, SatState & sat, bool allowConversion = false, bool skipUnbound = false) { 164 165 // skip unused assertions 165 166 if ( ! assn.second.isUsed ) return true; … … 180 181 if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer; 181 182 else if (!isUnboundType(thisArgType)) otypeKey = Mangle::mangle(thisArgType, Mangle::Type | Mangle::NoGenericParams); 183 else if (skipUnbound) return false; 182 184 183 185 candidates = sat.symtab.specialLookupId(kind, otypeKey); … … 205 207 206 208 // only keep candidates which unify 207 if ( unify( toType, adjType, newEnv, newNeed, have, newOpen, sat.symtab ) ) { 208 // set up binding slot for recursive assertions 209 ast::UniqueId crntResnSlot = 0; 210 if ( ! newNeed.empty() ) { 211 crntResnSlot = ++globalResnSlot; 212 for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; } 213 } 214 215 matches.emplace_back( 216 cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ), 217 std::move( newOpen ), crntResnSlot ); 209 210 ast::OpenVarSet closed; 211 findOpenVars( toType, newOpen, closed, newNeed, have, FirstClosed ); 212 findOpenVars( adjType, newOpen, closed, newNeed, have, FirstOpen ); 213 if ( allowConversion ) { 214 if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) { 215 // set up binding slot for recursive assertions 216 ast::UniqueId crntResnSlot = 0; 217 if ( ! newNeed.empty() ) { 218 crntResnSlot = ++globalResnSlot; 219 for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; } 220 } 221 222 matches.emplace_back( 223 cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ), 224 std::move( newOpen ), crntResnSlot ); 225 } 226 } 227 else { 228 if ( unifyExact( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) { 229 // set up binding slot for recursive assertions 230 ast::UniqueId crntResnSlot = 0; 231 if ( ! newNeed.empty() ) { 232 crntResnSlot = ++globalResnSlot; 233 for ( auto & a : newNeed ) { a.second.resnSlot = crntResnSlot; } 234 } 235 236 matches.emplace_back( 237 cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ), 238 std::move( newOpen ), crntResnSlot ); 239 } 218 240 } 219 241 } … … 413 435 // for each current mutually-compatible set of assertions 414 436 for ( SatState & sat : sats ) { 437 bool allowConversion = false; 415 438 // stop this branch if a better option is already found 416 439 auto it = thresholds.find( pruneKey( *sat.cand ) ); … … 418 441 419 442 // should a limit be imposed? worst case here is O(n^2) but very unlikely to happen. 443 420 444 for (unsigned resetCount = 0; ; ++resetCount) { 421 445 ast::AssertionList next; … … 424 448 for ( auto & assn : sat.need ) { 425 449 // fail early if any assertion is not satisfiable 426 if ( ! satisfyAssertion( assn, sat ) ) {450 if ( ! satisfyAssertion( assn, sat, allowConversion, !next.empty() ) ) { 427 451 next.emplace_back(assn); 428 452 // goto nextSat; … … 433 457 // fail if nothing resolves 434 458 else if (next.size() == sat.need.size()) { 435 Indenter tabs{ 3 }; 436 std::ostringstream ss; 437 ss << tabs << "Unsatisfiable alternative:\n"; 438 print( ss, *sat.cand, ++tabs ); 439 ss << (tabs-1) << "Could not satisfy assertion:\n"; 440 ast::print( ss, next[0].first, tabs ); 441 442 errors.emplace_back( ss.str() ); 443 goto nextSat; 444 } 459 if (allowConversion) { 460 Indenter tabs{ 3 }; 461 std::ostringstream ss; 462 ss << tabs << "Unsatisfiable alternative:\n"; 463 print( ss, *sat.cand, ++tabs ); 464 ss << (tabs-1) << "Could not satisfy assertion:\n"; 465 ast::print( ss, next[0].first, tabs ); 466 467 errors.emplace_back( ss.str() ); 468 goto nextSat; 469 } 470 471 else { 472 allowConversion = true; 473 continue; 474 } 475 } 476 allowConversion = false; 445 477 sat.need = std::move(next); 446 478 } -
src/ResolvExpr/Unify.cc
r8f1e035 ref1da0e2 693 693 } 694 694 695 namespace { 696 /// Replaces ttype variables with their bound types. 697 /// If this isn't done when satifying ttype assertions, then argument lists can have 698 /// different size and structure when they should be compatible. 699 struct TtypeExpander_new : public ast::WithShortCircuiting, public ast::PureVisitor { 700 ast::TypeEnvironment & tenv; 701 702 TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {} 703 704 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) { 705 if ( const ast::EqvClass * clz = tenv.lookup( *typeInst ) ) { 706 // expand ttype parameter into its actual type 707 if ( clz->data.kind == ast::TypeDecl::Ttype && clz->bound ) { 708 return clz->bound; 709 } 710 } 711 return typeInst; 712 } 713 }; 714 } 715 716 std::vector< ast::ptr< ast::Type > > flattenList( 717 const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env 718 ) { 719 std::vector< ast::ptr< ast::Type > > dst; 720 dst.reserve( src.size() ); 721 for ( const auto & d : src ) { 722 ast::Pass<TtypeExpander_new> expander{ env }; 723 // TtypeExpander pass is impure (may mutate nodes in place) 724 // need to make nodes shared to prevent accidental mutation 725 ast::ptr<ast::Type> dc = d->accept(expander); 726 auto types = flatten( dc ); 727 for ( ast::ptr< ast::Type > & t : types ) { 728 // outermost const, volatile, _Atomic qualifiers in parameters should not play 729 // a role in the unification of function types, since they do not determine 730 // whether a function is callable. 731 // NOTE: **must** consider at least mutex qualifier, since functions can be 732 // overloaded on outermost mutex and a mutex function has different 733 // requirements than a non-mutex function 734 remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic ); 735 dst.emplace_back( t ); 736 } 737 } 738 return dst; 739 } 740 695 741 class Unify_new final : public ast::WithShortCircuiting { 696 742 const ast::Type * type2; … … 764 810 765 811 private: 766 /// Replaces ttype variables with their bound types.767 /// If this isn't done when satifying ttype assertions, then argument lists can have768 /// different size and structure when they should be compatible.769 struct TtypeExpander_new : public ast::WithShortCircuiting, public ast::PureVisitor {770 ast::TypeEnvironment & tenv;771 772 TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {}773 774 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {775 if ( const ast::EqvClass * clz = tenv.lookup( *typeInst ) ) {776 // expand ttype parameter into its actual type777 if ( clz->data.kind == ast::TypeDecl::Ttype && clz->bound ) {778 return clz->bound;779 }780 }781 return typeInst;782 }783 };784 785 /// returns flattened version of `src`786 static std::vector< ast::ptr< ast::Type > > flattenList(787 const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env788 ) {789 std::vector< ast::ptr< ast::Type > > dst;790 dst.reserve( src.size() );791 for ( const auto & d : src ) {792 ast::Pass<TtypeExpander_new> expander{ env };793 // TtypeExpander pass is impure (may mutate nodes in place)794 // need to make nodes shared to prevent accidental mutation795 ast::ptr<ast::Type> dc = d->accept(expander);796 auto types = flatten( dc );797 for ( ast::ptr< ast::Type > & t : types ) {798 // outermost const, volatile, _Atomic qualifiers in parameters should not play799 // a role in the unification of function types, since they do not determine800 // whether a function is callable.801 // NOTE: **must** consider at least mutex qualifier, since functions can be802 // overloaded on outermost mutex and a mutex function has different803 // requirements than a non-mutex function804 remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );805 dst.emplace_back( t );806 }807 }808 return dst;809 }810 811 /// Creates a tuple type based on a list of DeclWithType812 template< typename Iter >813 static const ast::Type * tupleFromTypes( Iter crnt, Iter end ) {814 std::vector< ast::ptr< ast::Type > > types;815 while ( crnt != end ) {816 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure817 // that this results in a flat tuple818 flatten( *crnt, types );819 820 ++crnt;821 }822 823 return new ast::TupleType{ std::move(types) };824 }825 812 826 813 template< typename Iter > … … 1034 1021 private: 1035 1022 /// Creates a tuple type based on a list of Type 1036 static const ast::Type * tupleFromTypes( 1037 const std::vector< ast::ptr< ast::Type > > & tys 1038 ) { 1039 std::vector< ast::ptr< ast::Type > > out; 1040 for ( const ast::Type * ty : tys ) { 1041 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure 1042 // that this results in a flat tuple 1043 flatten( ty, out ); 1044 } 1045 1046 return new ast::TupleType{ std::move(out) }; 1047 } 1023 1048 1024 1049 1025 static bool unifyList( … … 1217 1193 } 1218 1194 1219 } else if ( ( common = commonType( t1, t2, widen, symtab, env, open ))) {1195 } else if ( common = commonType( t1, t2, env, need, have, open, widen, symtab )) { 1220 1196 // no exact unification, but common type 1221 1197 auto c = shallowCopy(common.get()); -
src/ResolvExpr/typeops.h
r8f1e035 ref1da0e2 138 138 Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer & indexer, TypeEnvironment & env, const OpenVarSet & openVars ); 139 139 ast::ptr< ast::Type > commonType( 140 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, WidenMode widen, 141 const ast::SymbolTable & symtab, ast::TypeEnvironment & env, const ast::OpenVarSet & open ); 140 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, 141 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 142 const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab 143 ); 144 // in Unify.cc 145 std::vector< ast::ptr< ast::Type > > flattenList( 146 const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env 147 ); 142 148 143 149 // in PolyCost.cc … … 181 187 182 188 /// flatten tuple type into existing list of types 183 staticinline void flatten(189 inline void flatten( 184 190 const ast::Type * type, std::vector< ast::ptr< ast::Type > > & out 185 191 ) { … … 194 200 195 201 /// flatten tuple type into list of types 196 staticinline std::vector< ast::ptr< ast::Type > > flatten( const ast::Type * type ) {202 inline std::vector< ast::ptr< ast::Type > > flatten( const ast::Type * type ) { 197 203 std::vector< ast::ptr< ast::Type > > out; 198 204 out.reserve( type->size() ); … … 200 206 return out; 201 207 } 208 209 template< typename Iter > 210 const ast::Type * tupleFromTypes( Iter crnt, Iter end ) { 211 std::vector< ast::ptr< ast::Type > > types; 212 while ( crnt != end ) { 213 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure 214 // that this results in a flat tuple 215 flatten( *crnt, types ); 216 217 ++crnt; 218 } 219 220 221 return new ast::TupleType{ std::move(types) }; 222 } 223 224 inline const ast::Type * tupleFromTypes( 225 const std::vector< ast::ptr< ast::Type > > & tys 226 ) { 227 return tupleFromTypes( tys.begin(), tys.end() ); 228 } 229 230 202 231 203 232 // in TypeEnvironment.cc -
tests/concurrent/.expect/ctor-check.txt
r8f1e035 ref1da0e2 2 2 ?{}: function 3 3 ... with parameters 4 this: lvaluereference to instance of struct Empty with body4 this: mutex reference to instance of struct Empty with body 5 5 ... returning nothing 6 6 with body
Note: See TracChangeset
for help on using the changeset viewer.