- Timestamp:
- Sep 20, 2022, 8:37:17 PM (3 years ago)
- Branches:
- ADT, ast-experimental, master, pthread-emulation
- Children:
- 53a768d
- Parents:
- 4520b77e (diff), ef1da0e2 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- src
- Files:
-
- 2 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Print.cpp
r4520b77e ra065f1f 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 }; … … 1635 1635 constexpr array<const char*, 3> Printer::Names::FuncSpecifiers; 1636 1636 constexpr array<const char*, 6> Printer::Names::StorageClasses; 1637 constexpr array<const char*, 6> Printer::Names::Qualifiers;1637 constexpr array<const char*, 5> Printer::Names::Qualifiers; 1638 1638 } -
src/AST/Type.hpp
r4520b77e ra065f1f 412 412 std::string typeString() const { return std::string("_") + std::to_string(formal_usage) + "_" + std::to_string(expr_id) + "_" + base->name; } 413 413 bool operator==(const TypeEnvKey & other) const { return base == other.base && formal_usage == other.formal_usage && expr_id == other.expr_id; } 414 415 414 }; 416 415 -
src/AST/TypeEnvironment.hpp
r4520b77e ra065f1f 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/AST/module.mk
r4520b77e ra065f1f 24 24 AST/Copy.cpp \ 25 25 AST/Copy.hpp \ 26 AST/Create.cpp \ 27 AST/Create.hpp \ 26 28 AST/CVQualifiers.hpp \ 27 29 AST/Decl.cpp \ -
src/CodeGen/CodeGenerator.cc
r4520b77e ra065f1f 494 494 assert( false ); 495 495 } // switch 496 } else if( varExpr->get_var()->get_linkage() == LinkageSpec::BuiltinCFA && varExpr->get_var()->get_name() == "intptr" ) { 497 // THIS is a hack to make it a constant until a proper constexpr solution is created 498 output << "((void*)"; 499 std::list< Expression* >::iterator arg = applicationExpr->get_args().begin(); 500 (*arg++)->accept( *visitor ); 501 output << ")"; 496 502 } else { 497 503 varExpr->accept( *visitor ); -
src/Concurrency/Waitfor.cc
r4520b77e ra065f1f 402 402 403 403 clause.target.function = nullptr; 404 clause.target.arguments. empty();404 clause.target.arguments.clear(); 405 405 clause.condition = nullptr; 406 406 } -
src/GenPoly/InstantiateGenericNew.cpp
r4520b77e ra065f1f 22 22 23 23 #include "AST/Copy.hpp" // for deepCopy 24 #include "AST/Create.hpp" // for asForward 24 25 #include "AST/Pass.hpp" // for Pass, WithGuard, WithShortCi... 25 26 #include "AST/TranslationUnit.hpp" // for TranslationUnit … … 255 256 void stripInstParams( ast::BaseInstType * inst ) { 256 257 inst->params.clear(); 257 }258 259 // TODO: I think this should become a generic helper.260 template<typename Aggr>261 Aggr * asForward( Aggr const * decl ) {262 if ( !decl->body ) {263 return nullptr;264 }265 Aggr * mut = ast::deepCopy( decl );266 mut->body = false;267 mut->members.clear();268 return mut;269 258 } 270 259 … … 553 542 // Forward declare before recursion. (TODO: Only when needed, #199.) 554 543 insert( inst, typeSubs, newDecl ); 555 if ( AggrDecl const * forwardDecl = as Forward( newDecl ) ) {544 if ( AggrDecl const * forwardDecl = ast::asForward( newDecl ) ) { 556 545 declsToAddBefore.push_back( forwardDecl ); 557 546 } -
src/GenPoly/Lvalue2.cc
r4520b77e ra065f1f 23 23 } 24 24 25 26 25 } -
src/ResolvExpr/CommonType.cc
r4520b77e ra065f1f 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
r4520b77e ra065f1f 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 { … … 657 659 cost = Cost::safe; 658 660 } 659 } else { 661 } 662 /* 663 else if ( const ast::FunctionType * dstFunc = dstAsPtr->base.as<ast::FunctionType>()) { 664 if (const ast::FunctionType * srcFunc = pointerType->base.as<ast::FunctionType>()) { 665 if (dstFunc->params.empty() && dstFunc->isVarArgs ) { 666 cost = Cost::unsafe; // assign any function to variadic fptr 667 } 668 } 669 else { 670 ast::AssertionSet need, have; // unused 671 ast::OpenVarSet open; 672 env.extractOpenVars(open); 673 ast::TypeEnvironment tenv = env; 674 if ( unify(dstAsPtr->base, pointerType->base, tenv, need, have, open, symtab) ) { 675 cost = Cost::safe; 676 } 677 } 678 // else infinity 679 } 680 */ 681 else { 660 682 int assignResult = ptrsAssignable( pointerType->base, dstAsPtr->base, env ); 661 683 if ( 0 < assignResult && tq1 <= tq2 ) { -
src/ResolvExpr/SatisfyAssertions.cpp
r4520b77e ra065f1f 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
r4520b77e ra065f1f 707 707 } 708 708 709 namespace { 710 /// Replaces ttype variables with their bound types. 711 /// If this isn't done when satifying ttype assertions, then argument lists can have 712 /// different size and structure when they should be compatible. 713 struct TtypeExpander_new : public ast::WithShortCircuiting, public ast::PureVisitor { 714 ast::TypeEnvironment & tenv; 715 716 TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {} 717 718 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) { 719 if ( const ast::EqvClass * clz = tenv.lookup( *typeInst ) ) { 720 // expand ttype parameter into its actual type 721 if ( clz->data.kind == ast::TypeDecl::Ttype && clz->bound ) { 722 return clz->bound; 723 } 724 } 725 return typeInst; 726 } 727 }; 728 } 729 730 std::vector< ast::ptr< ast::Type > > flattenList( 731 const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env 732 ) { 733 std::vector< ast::ptr< ast::Type > > dst; 734 dst.reserve( src.size() ); 735 for ( const auto & d : src ) { 736 ast::Pass<TtypeExpander_new> expander{ env }; 737 // TtypeExpander pass is impure (may mutate nodes in place) 738 // need to make nodes shared to prevent accidental mutation 739 ast::ptr<ast::Type> dc = d->accept(expander); 740 auto types = flatten( dc ); 741 for ( ast::ptr< ast::Type > & t : types ) { 742 // outermost const, volatile, _Atomic qualifiers in parameters should not play 743 // a role in the unification of function types, since they do not determine 744 // whether a function is callable. 745 // NOTE: **must** consider at least mutex qualifier, since functions can be 746 // overloaded on outermost mutex and a mutex function has different 747 // requirements than a non-mutex function 748 remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic ); 749 dst.emplace_back( t ); 750 } 751 } 752 return dst; 753 } 754 709 755 class Unify_new final : public ast::WithShortCircuiting { 710 756 const ast::Type * type2; … … 778 824 779 825 private: 780 /// Replaces ttype variables with their bound types.781 /// If this isn't done when satifying ttype assertions, then argument lists can have782 /// different size and structure when they should be compatible.783 struct TtypeExpander_new : public ast::WithShortCircuiting, public ast::PureVisitor {784 ast::TypeEnvironment & tenv;785 786 TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {}787 788 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {789 if ( const ast::EqvClass * clz = tenv.lookup( *typeInst ) ) {790 // expand ttype parameter into its actual type791 if ( clz->data.kind == ast::TypeDecl::Ttype && clz->bound ) {792 return clz->bound;793 }794 }795 return typeInst;796 }797 };798 799 /// returns flattened version of `src`800 static std::vector< ast::ptr< ast::Type > > flattenList(801 const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env802 ) {803 std::vector< ast::ptr< ast::Type > > dst;804 dst.reserve( src.size() );805 for ( const auto & d : src ) {806 ast::Pass<TtypeExpander_new> expander{ env };807 // TtypeExpander pass is impure (may mutate nodes in place)808 // need to make nodes shared to prevent accidental mutation809 ast::ptr<ast::Type> dc = d->accept(expander);810 auto types = flatten( dc );811 for ( ast::ptr< ast::Type > & t : types ) {812 // outermost const, volatile, _Atomic qualifiers in parameters should not play813 // a role in the unification of function types, since they do not determine814 // whether a function is callable.815 // NOTE: **must** consider at least mutex qualifier, since functions can be816 // overloaded on outermost mutex and a mutex function has different817 // requirements than a non-mutex function818 remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );819 dst.emplace_back( t );820 }821 }822 return dst;823 }824 825 /// Creates a tuple type based on a list of DeclWithType826 template< typename Iter >827 static const ast::Type * tupleFromTypes( Iter crnt, Iter end ) {828 std::vector< ast::ptr< ast::Type > > types;829 while ( crnt != end ) {830 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure831 // that this results in a flat tuple832 flatten( *crnt, types );833 834 ++crnt;835 }836 837 return new ast::TupleType{ std::move(types) };838 }839 826 840 827 template< typename Iter > … … 1048 1035 private: 1049 1036 /// Creates a tuple type based on a list of Type 1050 static const ast::Type * tupleFromTypes( 1051 const std::vector< ast::ptr< ast::Type > > & tys 1052 ) { 1053 std::vector< ast::ptr< ast::Type > > out; 1054 for ( const ast::Type * ty : tys ) { 1055 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure 1056 // that this results in a flat tuple 1057 flatten( ty, out ); 1058 } 1059 1060 return new ast::TupleType{ std::move(out) }; 1061 } 1037 1062 1038 1063 1039 static bool unifyList( … … 1231 1207 } 1232 1208 1233 } else if ( ( common = commonType( t1, t2, widen, symtab, env, open ))) {1209 } else if ( common = commonType( t1, t2, env, need, have, open, widen, symtab )) { 1234 1210 // no exact unification, but common type 1235 1211 auto c = shallowCopy(common.get()); -
src/ResolvExpr/typeops.h
r4520b77e ra065f1f 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
Note:
See TracChangeset
for help on using the changeset viewer.