Changes in src/ResolvExpr/Unify.cc [302ef2a:07de76b]
- File:
-
- 1 edited
-
src/ResolvExpr/Unify.cc (modified) (30 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Unify.cc
r302ef2a r07de76b 25 25 #include <vector> 26 26 27 #include "AST/Copy.hpp"28 27 #include "AST/Decl.hpp" 29 28 #include "AST/Node.hpp" 30 29 #include "AST/Pass.hpp" 31 #include "AST/Print.hpp"32 30 #include "AST/Type.hpp" 33 31 #include "AST/TypeEnvironment.hpp" … … 137 135 findOpenVars( newSecond, open, closed, need, have, FirstOpen ); 138 136 139 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 137 return unifyExact( 138 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 140 139 } 141 140 … … 149 148 newFirst->get_qualifiers() = Type::Qualifiers(); 150 149 newSecond->get_qualifiers() = Type::Qualifiers(); 151 150 /// std::cerr << "first is "; 151 /// first->print( std::cerr ); 152 /// std::cerr << std::endl << "second is "; 153 /// second->print( std::cerr ); 154 /// std::cerr << std::endl << "newFirst is "; 155 /// newFirst->print( std::cerr ); 156 /// std::cerr << std::endl << "newSecond is "; 157 /// newSecond->print( std::cerr ); 158 /// std::cerr << std::endl; 152 159 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 153 160 delete newFirst; … … 163 170 ast::AssertionSet need, have; 164 171 165 ast::Type * newFirst = shallowCopy( first ); 166 ast::Type * newSecond = shallowCopy( second ); 167 newFirst ->qualifiers = {}; 168 newSecond->qualifiers = {}; 169 ast::ptr< ast::Type > t1_(newFirst ); 170 ast::ptr< ast::Type > t2_(newSecond); 171 172 ast::ptr< ast::Type > subFirst = env.apply(newFirst).node; 173 ast::ptr< ast::Type > subSecond = env.apply(newSecond).node; 172 ast::ptr<ast::Type> newFirst{ first }, newSecond{ second }; 173 env.apply( newFirst ); 174 env.apply( newSecond ); 175 reset_qualifiers( newFirst ); 176 reset_qualifiers( newSecond ); 174 177 175 178 return unifyExact( 176 subFirst, 177 subSecond, 178 newEnv, need, have, open, noWiden(), symtab ); 179 newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab ); 179 180 } 180 181 … … 325 326 326 327 void markAssertionSet( AssertionSet &assertions, DeclarationWithType *assert ) { 328 /// std::cerr << "assertion set is" << std::endl; 329 /// printAssertionSet( assertions, std::cerr, 8 ); 330 /// std::cerr << "looking for "; 331 /// assert->print( std::cerr ); 332 /// std::cerr << std::endl; 327 333 AssertionSet::iterator i = assertions.find( assert ); 328 334 if ( i != assertions.end() ) { 335 /// std::cerr << "found it!" << std::endl; 329 336 i->second.isUsed = true; 330 337 } // if … … 395 402 396 403 template< typename Iterator1, typename Iterator2 > 397 bool unify TypeList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {404 bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 398 405 auto get_type = [](DeclarationWithType * dwt){ return dwt->get_type(); }; 399 406 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) { … … 489 496 || flatOther->isTtype() 490 497 ) { 491 if ( unify TypeList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {492 if ( unify TypeList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {498 if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 499 if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 493 500 494 501 // the original types must be used in mark assertions, since pointer comparisons are used … … 702 709 const ast::SymbolTable & symtab; 703 710 public: 704 static size_t traceId;705 711 bool result; 706 712 … … 767 773 /// If this isn't done when satifying ttype assertions, then argument lists can have 768 774 /// different size and structure when they should be compatible. 769 struct TtypeExpander_new : public ast::WithShortCircuiting , public ast::PureVisitor{775 struct TtypeExpander_new : public ast::WithShortCircuiting { 770 776 ast::TypeEnvironment & tenv; 771 777 … … 773 779 774 780 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) { 775 if ( const ast::EqvClass * clz = tenv.lookup( *typeInst) ) {781 if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) { 776 782 // expand ttype parameter into its actual type 777 783 if ( clz->data.kind == ast::TypeDecl::Ttype && clz->bound ) { … … 784 790 785 791 /// 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 & env792 static std::vector< ast::ptr< ast::DeclWithType > > flattenList( 793 const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env 788 794 ) { 789 std::vector< ast::ptr< ast:: Type > > dst;795 std::vector< ast::ptr< ast::DeclWithType > > dst; 790 796 dst.reserve( src.size() ); 791 for ( const a uto &d : src ) {797 for ( const ast::DeclWithType * d : src ) { 792 798 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 mutation 795 ast::ptr<ast::Type> dc = d->accept(expander); 796 auto types = flatten( dc ); 799 d = d->accept( expander ); 800 auto types = flatten( d->get_type() ); 797 801 for ( ast::ptr< ast::Type > & t : types ) { 798 802 // outermost const, volatile, _Atomic qualifiers in parameters should not play … … 803 807 // requirements than a non-mutex function 804 808 remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic ); 805 dst.emplace_back( t);809 dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } ); 806 810 } 807 811 } … … 811 815 /// Creates a tuple type based on a list of DeclWithType 812 816 template< typename Iter > 813 static const ast::Type * tupleFromTypes( Iter crnt, Iter end ) {817 static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) { 814 818 std::vector< ast::ptr< ast::Type > > types; 815 819 while ( crnt != end ) { 816 820 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure 817 821 // that this results in a flat tuple 818 flatten( *crnt, types );822 flatten( (*crnt)->get_type(), types ); 819 823 820 824 ++crnt; 821 825 } 822 826 823 return new ast::TupleType{ std::move(types)};827 return { new ast::TupleType{ std::move(types) } }; 824 828 } 825 829 826 830 template< typename Iter > 827 static bool unify TypeList(831 static bool unifyDeclList( 828 832 Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env, 829 833 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, … … 831 835 ) { 832 836 while ( crnt1 != end1 && crnt2 != end2 ) { 833 const ast::Type * t1 = *crnt1;834 const ast::Type * t2 = *crnt2;837 const ast::Type * t1 = (*crnt1)->get_type(); 838 const ast::Type * t2 = (*crnt2)->get_type(); 835 839 bool isTuple1 = Tuples::isTtype( t1 ); 836 840 bool isTuple2 = Tuples::isTtype( t2 ); … … 840 844 // combine remainder of list2, then unify 841 845 return unifyExact( 842 t1, tupleFrom Types( crnt2, end2 ), env, need, have, open,846 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 843 847 noWiden(), symtab ); 844 848 } else if ( ! isTuple1 && isTuple2 ) { 845 849 // combine remainder of list1, then unify 846 850 return unifyExact( 847 tupleFrom Types( crnt1, end1 ), t2, env, need, have, open,851 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 848 852 noWiden(), symtab ); 849 853 } … … 860 864 if ( crnt1 != end1 ) { 861 865 // try unifying empty tuple with ttype 862 const ast::Type * t1 = *crnt1;866 const ast::Type * t1 = (*crnt1)->get_type(); 863 867 if ( ! Tuples::isTtype( t1 ) ) return false; 864 868 return unifyExact( 865 t1, tupleFrom Types( crnt2, end2 ), env, need, have, open,869 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 866 870 noWiden(), symtab ); 867 871 } else if ( crnt2 != end2 ) { 868 872 // try unifying empty tuple with ttype 869 const ast::Type * t2 = *crnt2;873 const ast::Type * t2 = (*crnt2)->get_type(); 870 874 if ( ! Tuples::isTtype( t2 ) ) return false; 871 875 return unifyExact( 872 tupleFrom Types( crnt1, end1 ), t2, env, need, have, open,876 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 873 877 noWiden(), symtab ); 874 878 } … … 877 881 } 878 882 879 static bool unify TypeList(880 const std::vector< ast::ptr< ast:: Type > > & list1,881 const std::vector< ast::ptr< ast:: Type > > & list2,883 static bool unifyDeclList( 884 const std::vector< ast::ptr< ast::DeclWithType > > & list1, 885 const std::vector< ast::ptr< ast::DeclWithType > > & list2, 882 886 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 883 887 const ast::OpenVarSet & open, const ast::SymbolTable & symtab 884 888 ) { 885 return unify TypeList(889 return unifyDeclList( 886 890 list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open, 887 891 symtab ); 888 892 } 889 893 890 static void markAssertionSet( ast::AssertionSet & assns, const ast:: VariableExpr* assn ) {894 static void markAssertionSet( ast::AssertionSet & assns, const ast::DeclWithType * assn ) { 891 895 auto i = assns.find( assn ); 892 896 if ( i != assns.end() ) { … … 898 902 static void markAssertions( 899 903 ast::AssertionSet & assn1, ast::AssertionSet & assn2, 900 const ast:: FunctionType * type904 const ast::ParameterizedType * type 901 905 ) { 902 for ( auto & assert : type->assertions ) { 903 markAssertionSet( assn1, assert ); 904 markAssertionSet( assn2, assert ); 906 for ( const auto & tyvar : type->forall ) { 907 for ( const ast::DeclWithType * assert : tyvar->assertions ) { 908 markAssertionSet( assn1, assert ); 909 markAssertionSet( assn2, assert ); 910 } 905 911 } 906 912 } … … 926 932 ) return; 927 933 928 if ( ! unify TypeList( params, params2, tenv, need, have, open, symtab ) ) return;929 if ( ! unify TypeList(934 if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return; 935 if ( ! unifyDeclList( 930 936 func->returns, func2->returns, tenv, need, have, open, symtab ) ) return; 931 937 … … 937 943 938 944 private: 939 // Returns: other, cast as XInstType 940 // Assigns this->result: whether types are compatible (up to generic parameters) 941 template< typename XInstType > 942 const XInstType * handleRefType( const XInstType * inst, const ast::Type * other ) { 945 template< typename RefType > 946 const RefType * handleRefType( const RefType * inst, const ast::Type * other ) { 943 947 // check that the other type is compatible and named the same 944 auto otherInst = dynamic_cast< const XInstType * >( other );945 this->result = otherInst && inst->name == otherInst->name;948 auto otherInst = dynamic_cast< const RefType * >( other ); 949 result = otherInst && inst->name == otherInst->name; 946 950 return otherInst; 947 951 } … … 964 968 } 965 969 966 template< typename XInstType >967 void handleGenericRefType( const XInstType * inst, const ast::Type * other ) {970 template< typename RefType > 971 void handleGenericRefType( const RefType * inst, const ast::Type * other ) { 968 972 // check that other type is compatible and named the same 969 const XInstType * otherInst= handleRefType( inst, other );970 if ( ! this->result) return;973 const RefType * inst2 = handleRefType( inst, other ); 974 if ( ! inst2 ) return; 971 975 972 976 // check that parameters of types unify, if any 973 977 const std::vector< ast::ptr< ast::Expr > > & params = inst->params; 974 const std::vector< ast::ptr< ast::Expr > > & params2 = otherInst->params;978 const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params; 975 979 976 980 auto it = params.begin(); … … 1028 1032 1029 1033 void postvisit( const ast::TypeInstType * typeInst ) { 1030 assert( open.find( *typeInst) == open.end() );1034 assert( open.find( typeInst->name ) == open.end() ); 1031 1035 handleRefType( typeInst, type2 ); 1032 1036 } … … 1034 1038 private: 1035 1039 /// Creates a tuple type based on a list of Type 1036 static const ast::Type *tupleFromTypes(1040 static ast::ptr< ast::Type > tupleFromTypes( 1037 1041 const std::vector< ast::ptr< ast::Type > > & tys 1038 1042 ) { … … 1110 1114 1111 1115 ast::Pass<TtypeExpander_new> expander{ tenv }; 1112 1113 1116 const ast::Type * flat = tuple->accept( expander ); 1114 1117 const ast::Type * flat2 = tuple2->accept( expander ); … … 1137 1140 }; 1138 1141 1139 // size_t Unify_new::traceId = Stats::Heap::new_stacktrace_id("Unify_new");1140 1142 bool unify( 1141 1143 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, … … 1169 1171 auto var2 = dynamic_cast< const ast::TypeInstType * >( type2 ); 1170 1172 ast::OpenVarSet::const_iterator 1171 entry1 = var1 ? open.find( *var1) : open.end(),1172 entry2 = var2 ? open.find( *var2) : open.end();1173 entry1 = var1 ? open.find( var1->name ) : open.end(), 1174 entry2 = var2 ? open.find( var2->name ) : open.end(); 1173 1175 bool isopen1 = entry1 != open.end(); 1174 1176 bool isopen2 = entry2 != open.end(); … … 1186 1188 ast::Pass<Unify_new> comparator{ type2, env, need, have, open, widen, symtab }; 1187 1189 type1->accept( comparator ); 1188 return comparator. core.result;1190 return comparator.pass.result; 1189 1191 } 1190 1192 } … … 1200 1202 // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and 1201 1203 // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1 1202 ast::Type * t1 = shallowCopy(type1.get()); 1203 ast::Type * t2 = shallowCopy(type2.get()); 1204 t1->qualifiers = {}; 1205 t2->qualifiers = {}; 1206 ast::ptr< ast::Type > t1_(t1); 1207 ast::ptr< ast::Type > t2_(t2); 1204 ast::ptr<ast::Type> t1{ type1 }, t2{ type2 }; 1205 reset_qualifiers( t1 ); 1206 reset_qualifiers( t2 ); 1208 1207 1209 1208 if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) { 1209 t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones 1210 1210 1211 // if exact unification on unqualified types, try to merge qualifiers 1211 1212 if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) { 1212 t1->qualifiers = q1 | q2;1213 common = t1;1213 common = type1; 1214 reset_qualifiers( common, q1 | q2 ); 1214 1215 return true; 1215 1216 } else { … … 1218 1219 1219 1220 } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) { 1221 t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones 1222 1220 1223 // no exact unification, but common type 1221 auto c = shallowCopy(common.get()); 1222 c->qualifiers = q1 | q2; 1223 common = c; 1224 reset_qualifiers( common, q1 | q2 ); 1224 1225 return true; 1225 1226 } else { … … 1230 1231 ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ) { 1231 1232 if ( func->returns.empty() ) return new ast::VoidType{}; 1232 if ( func->returns.size() == 1 ) return func->returns[0] ;1233 if ( func->returns.size() == 1 ) return func->returns[0]->get_type(); 1233 1234 1234 1235 std::vector<ast::ptr<ast::Type>> tys; 1235 for ( const a uto &decl : func->returns ) {1236 tys.emplace_back( decl );1236 for ( const ast::DeclWithType * decl : func->returns ) { 1237 tys.emplace_back( decl->get_type() ); 1237 1238 } 1238 1239 return new ast::TupleType{ std::move(tys) };
Note:
See TracChangeset
for help on using the changeset viewer.