Changes in / [88ef2af:9f10d1f2]
- Location:
- src
- Files:
-
- 2 deleted
- 13 edited
-
Makefile.in (modified) (5 diffs)
-
Parser/DeclarationNode.cc (modified) (3 diffs)
-
Parser/parser.yy (modified) (8 diffs)
-
ResolvExpr/Alternative.cc (modified) (2 diffs)
-
ResolvExpr/Alternative.h (modified) (3 diffs)
-
ResolvExpr/AlternativeFinder.cc (modified) (23 diffs)
-
ResolvExpr/AlternativeFinder.h (modified) (3 diffs)
-
ResolvExpr/ExplodedActual.cc (deleted)
-
ResolvExpr/ExplodedActual.h (deleted)
-
ResolvExpr/Resolver.cc (modified) (2 diffs)
-
ResolvExpr/module.mk (modified) (1 diff)
-
ResolvExpr/typeops.h (modified) (3 diffs)
-
SymTab/Validate.cc (modified) (4 diffs)
-
Tuples/TupleAssignment.cc (modified) (1 diff)
-
tests/.expect/castError.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Makefile.in
r88ef2af r9f10d1f2 210 210 ResolvExpr/driver_cfa_cpp-TypeEnvironment.$(OBJEXT) \ 211 211 ResolvExpr/driver_cfa_cpp-CurrentObject.$(OBJEXT) \ 212 ResolvExpr/driver_cfa_cpp-ExplodedActual.$(OBJEXT) \213 212 SymTab/driver_cfa_cpp-Indexer.$(OBJEXT) \ 214 213 SymTab/driver_cfa_cpp-Mangler.$(OBJEXT) \ … … 512 511 ResolvExpr/FindOpenVars.cc ResolvExpr/PolyCost.cc \ 513 512 ResolvExpr/Occurs.cc ResolvExpr/TypeEnvironment.cc \ 514 ResolvExpr/CurrentObject.cc ResolvExpr/ExplodedActual.cc \ 515 SymTab/Indexer.cc SymTab/Mangler.cc SymTab/Validate.cc \ 516 SymTab/FixFunction.cc SymTab/ImplementationType.cc \ 517 SymTab/TypeEquality.cc SymTab/Autogen.cc SynTree/Type.cc \ 518 SynTree/VoidType.cc SynTree/BasicType.cc \ 519 SynTree/PointerType.cc SynTree/ArrayType.cc \ 520 SynTree/ReferenceType.cc SynTree/FunctionType.cc \ 521 SynTree/ReferenceToType.cc SynTree/TupleType.cc \ 522 SynTree/TypeofType.cc SynTree/AttrType.cc \ 513 ResolvExpr/CurrentObject.cc SymTab/Indexer.cc \ 514 SymTab/Mangler.cc SymTab/Validate.cc SymTab/FixFunction.cc \ 515 SymTab/ImplementationType.cc SymTab/TypeEquality.cc \ 516 SymTab/Autogen.cc SynTree/Type.cc SynTree/VoidType.cc \ 517 SynTree/BasicType.cc SynTree/PointerType.cc \ 518 SynTree/ArrayType.cc SynTree/ReferenceType.cc \ 519 SynTree/FunctionType.cc SynTree/ReferenceToType.cc \ 520 SynTree/TupleType.cc SynTree/TypeofType.cc SynTree/AttrType.cc \ 523 521 SynTree/VarArgsType.cc SynTree/ZeroOneType.cc \ 524 522 SynTree/Constant.cc SynTree/Expression.cc SynTree/TupleExpr.cc \ … … 827 825 ResolvExpr/$(am__dirstamp) \ 828 826 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 829 ResolvExpr/driver_cfa_cpp-ExplodedActual.$(OBJEXT): \830 ResolvExpr/$(am__dirstamp) \831 ResolvExpr/$(DEPDIR)/$(am__dirstamp)832 827 SymTab/$(am__dirstamp): 833 828 @$(MKDIR_P) SymTab … … 1027 1022 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ConversionCost.Po@am__quote@ 1028 1023 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-CurrentObject.Po@am__quote@ 1029 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Po@am__quote@1030 1024 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-FindOpenVars.Po@am__quote@ 1031 1025 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Occurs.Po@am__quote@ … … 1970 1964 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-CurrentObject.obj `if test -f 'ResolvExpr/CurrentObject.cc'; then $(CYGPATH_W) 'ResolvExpr/CurrentObject.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/CurrentObject.cc'; fi` 1971 1965 1972 ResolvExpr/driver_cfa_cpp-ExplodedActual.o: ResolvExpr/ExplodedActual.cc1973 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-ExplodedActual.o -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Tpo -c -o ResolvExpr/driver_cfa_cpp-ExplodedActual.o `test -f 'ResolvExpr/ExplodedActual.cc' || echo '$(srcdir)/'`ResolvExpr/ExplodedActual.cc1974 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Po1975 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ResolvExpr/ExplodedActual.cc' object='ResolvExpr/driver_cfa_cpp-ExplodedActual.o' libtool=no @AMDEPBACKSLASH@1976 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@1977 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-ExplodedActual.o `test -f 'ResolvExpr/ExplodedActual.cc' || echo '$(srcdir)/'`ResolvExpr/ExplodedActual.cc1978 1979 ResolvExpr/driver_cfa_cpp-ExplodedActual.obj: ResolvExpr/ExplodedActual.cc1980 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT ResolvExpr/driver_cfa_cpp-ExplodedActual.obj -MD -MP -MF ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Tpo -c -o ResolvExpr/driver_cfa_cpp-ExplodedActual.obj `if test -f 'ResolvExpr/ExplodedActual.cc'; then $(CYGPATH_W) 'ResolvExpr/ExplodedActual.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/ExplodedActual.cc'; fi`1981 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Tpo ResolvExpr/$(DEPDIR)/driver_cfa_cpp-ExplodedActual.Po1982 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='ResolvExpr/ExplodedActual.cc' object='ResolvExpr/driver_cfa_cpp-ExplodedActual.obj' libtool=no @AMDEPBACKSLASH@1983 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@1984 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-ExplodedActual.obj `if test -f 'ResolvExpr/ExplodedActual.cc'; then $(CYGPATH_W) 'ResolvExpr/ExplodedActual.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/ExplodedActual.cc'; fi`1985 1986 1966 SymTab/driver_cfa_cpp-Indexer.o: SymTab/Indexer.cc 1987 1967 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-Indexer.o -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-Indexer.Tpo -c -o SymTab/driver_cfa_cpp-Indexer.o `test -f 'SymTab/Indexer.cc' || echo '$(srcdir)/'`SymTab/Indexer.cc -
src/Parser/DeclarationNode.cc
r88ef2af r9f10d1f2 10 10 // Created On : Sat May 16 12:34:05 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Nov 20 09:21:52201713 // Update Count : 10 3112 // Last Modified On : Sat Sep 23 18:16:48 2017 13 // Update Count : 1024 14 14 // 15 15 … … 509 509 510 510 DeclarationNode * DeclarationNode::addQualifiers( DeclarationNode * q ) { 511 if ( ! q ) { delete q; return this; } // empty qualifier511 if ( ! q ) { delete q; return this; } 512 512 513 513 checkSpecifiers( q ); 514 514 copySpecifiers( q ); 515 515 516 if ( ! q->type ) { delete q; return this; } 516 if ( ! q->type ) { 517 delete q; 518 return this; 519 } // if 517 520 518 521 if ( ! type ) { 519 type = q->type; // reuse structure522 type = q->type; // reuse this structure 520 523 q->type = nullptr; 521 524 delete q; … … 523 526 } // if 524 527 525 if ( q->type->forall ) { // forall qualifier ?526 if ( type->forall ) { // polymorphic routine ?527 type->forall->appendList( q->type->forall ); // augment forall qualifier528 if ( q->type->forall ) { 529 if ( type->forall ) { 530 type->forall->appendList( q->type->forall ); 528 531 } else { 529 if ( type->kind == TypeData::Aggregate ) { // struct/union ? 530 if ( type->aggregate.params ) { // polymorphic ? 531 type->aggregate.params->appendList( q->type->forall ); // augment forall qualifier 532 } else { // not polymorphic 533 type->aggregate.params = q->type->forall; // make polymorphic type 534 // change implicit typedef from TYPEDEFname to TYPEGENname 535 typedefTable.changeKind( *type->aggregate.name, TypedefTable::TG ); 536 } // if 537 } else { // not polymorphic 538 type->forall = q->type->forall; // make polymorphic routine 532 if ( type->kind == TypeData::Aggregate ) { 533 type->aggregate.params = q->type->forall; 534 // change implicit typedef from TYPEDEFname to TYPEGENname 535 typedefTable.changeKind( *type->aggregate.name, TypedefTable::TG ); 536 } else { 537 type->forall = q->type->forall; 539 538 } // if 540 539 } // if 541 q->type->forall = nullptr; // forall qualifier moved540 q->type->forall = nullptr; 542 541 } // if 543 542 -
src/Parser/parser.yy
r88ef2af r9f10d1f2 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Nov 20 09:45:36201713 // Update Count : 2 94512 // Last Modified On : Wed Oct 25 12:28:54 2017 13 // Update Count : 2893 14 14 // 15 15 … … 114 114 } // for 115 115 } // distExt 116 117 // There is an ambiguity for inline generic-routine return-types and generic routines.118 // forall( otype T ) struct S { int i; } bar( T ) {}119 // Does the forall bind to the struct or the routine, and how would it be possible to explicitly specify the binding.120 // forall( otype T ) struct S { int T; } forall( otype W ) bar( W ) {}121 122 void rebindForall( DeclarationNode * declSpec, DeclarationNode * funcDecl ) {123 if ( declSpec->type->kind == TypeData::Aggregate ) { // return is aggregate definition124 funcDecl->type->forall = declSpec->type->aggregate.params; // move forall from aggregate to function type125 declSpec->type->aggregate.params = nullptr;126 } // if127 } // rebindForall128 116 129 117 bool forall = false; // aggregate have one or more forall qualifiers ? … … 360 348 361 349 362 // Handle shift/reduce conflict for dangling else by shifting the ELSE token. For example, this string is ambiguous: 363 // .---------. matches IF '(' comma_expression ')' statement . (reduce) 364 // if ( C ) S1 else S2 365 // `-----------------' matches IF '(' comma_expression ')' statement . (shift) ELSE statement */ 350 // Handle single shift/reduce conflict for dangling else by shifting the ELSE token. For example, this string 351 // is ambiguous: 352 // .---------. matches IF '(' comma_expression ')' statement . (reduce) 353 // if ( C ) S1 else S2 354 // `-----------------' matches IF '(' comma_expression ')' statement . (shift) ELSE statement */ 366 355 // Similar issues exit with the waitfor statement. 367 356 … … 372 361 %precedence TIMEOUT // token precedence for start of TIMEOUT in WAITFOR statement 373 362 %precedence ELSE // token precedence for start of else clause in IF/WAITFOR statement 374 375 // Handle shift/reduce conflict for generic type by shifting the '(' token. For example, this string is ambiguous:376 // forall( otype T ) struct Foo { T v; };377 // .-----. matches pointer to function returning a generic (which is impossible without a type)378 // Foo ( *fp )( int );379 // `---' matches start of TYPEGENname '('380 // Must be:381 // Foo( int ) ( *fp )( int );382 383 // Order of these lines matters (low-to-high precedence).384 %precedence TYPEGENname385 %precedence '('386 363 387 364 %locations // support location tracking for error messages … … 1788 1765 1789 1766 typegen_name: // CFA 1790 TYPEGENname 1791 { $$ = DeclarationNode::newFromTypeGen( $1, nullptr ); } 1792 | TYPEGENname '(' ')' 1767 TYPEGENname '(' ')' 1793 1768 { $$ = DeclarationNode::newFromTypeGen( $1, nullptr ); } 1794 1769 | TYPEGENname '(' type_list ')' … … 1834 1809 } 1835 1810 | aggregate_key attribute_list_opt typegen_name // CFA 1836 { 1837 // Create new generic declaration with same name as previous forward declaration, where the IDENTIFIER is 1838 // switched to a TYPEGENname. Link any generic arguments from typegen_name to new generic declaration and 1839 // delete newFromTypeGen. 1840 $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $3->type->symbolic.actuals, nullptr, false )->addQualifiers( $2 ); 1841 $3->type->symbolic.name = nullptr; 1842 $3->type->symbolic.actuals = nullptr; 1843 delete $3; 1844 } 1811 { $$ = $3->addQualifiers( $2 ); } 1845 1812 ; 1846 1813 … … 2413 2380 | declaration_specifier function_declarator with_clause_opt compound_statement 2414 2381 { 2415 rebindForall( $1, $2 );2416 2382 typedefTable.addToEnclosingScope( TypedefTable::ID ); 2417 2383 typedefTable.leaveScope(); … … 2440 2406 | declaration_specifier KR_function_declarator KR_declaration_list_opt with_clause_opt compound_statement 2441 2407 { 2442 rebindForall( $1, $2 );2443 2408 typedefTable.addToEnclosingScope( TypedefTable::ID ); 2444 2409 typedefTable.leaveScope(); -
src/ResolvExpr/Alternative.cc
r88ef2af r9f10d1f2 18 18 #include <ostream> // for operator<<, ostream, basic_o... 19 19 #include <string> // for operator<<, char_traits, string 20 #include <utility> // for move21 20 22 21 #include "Common/utility.h" // for maybeClone … … 82 81 os << std::endl; 83 82 } 84 85 void splice( AltList& dst, AltList& src ) {86 dst.reserve( dst.size() + src.size() );87 for ( Alternative& alt : src ) {88 dst.push_back( std::move(alt) );89 }90 src.clear();91 }92 93 void spliceBegin( AltList& dst, AltList& src ) {94 splice( src, dst );95 dst.swap( src );96 }97 98 83 } // namespace ResolvExpr 99 84 -
src/ResolvExpr/Alternative.h
r88ef2af r9f10d1f2 17 17 18 18 #include <iosfwd> // for ostream 19 #include < vector> // for vector19 #include <list> // for list 20 20 21 21 #include "Cost.h" // for Cost … … 25 25 26 26 namespace ResolvExpr { 27 struct Alternative; 28 29 typedef std::list< Alternative > AltList; 30 27 31 struct Alternative { 28 32 Alternative(); … … 42 46 TypeEnvironment env; 43 47 }; 44 45 typedef std::vector< Alternative > AltList;46 47 /// Moves all elements from src to the end of dst48 void splice( AltList& dst, AltList& src );49 50 /// Moves all elements from src to the beginning of dst51 void spliceBegin( AltList& dst, AltList& src );52 48 } // namespace ResolvExpr 53 49 -
src/ResolvExpr/AlternativeFinder.cc
r88ef2af r9f10d1f2 16 16 #include <algorithm> // for copy 17 17 #include <cassert> // for strict_dynamic_cast, assert, assertf 18 #include <cstddef> // for size_t19 18 #include <iostream> // for operator<<, cerr, ostream, endl 20 19 #include <iterator> // for back_insert_iterator, back_inserter 21 20 #include <list> // for _List_iterator, list, _List_const_... 22 21 #include <map> // for _Rb_tree_iterator, map, _Rb_tree_c... 23 #include <memory> // for allocator_traits<>::value_type , unique_ptr22 #include <memory> // for allocator_traits<>::value_type 24 23 #include <utility> // for pair 25 24 #include <vector> // for vector … … 30 29 #include "Common/utility.h" // for deleteAll, printAll, CodeLocation 31 30 #include "Cost.h" // for Cost, Cost::zero, operator<<, Cost... 32 #include "ExplodedActual.h" // for ExplodedActual33 31 #include "InitTweak/InitTweak.h" // for getFunctionName 34 32 #include "RenameVars.h" // for RenameVars, global_renamer … … 52 50 #define PRINT( text ) if ( resolvep ) { text } 53 51 //#define DEBUG_COST 54 55 using std::move;56 57 /// copies any copyable type58 template<typename T>59 T copy(const T& x) { return x; }60 52 61 53 namespace ResolvExpr { … … 195 187 printAlts( alternatives, std::cerr ); 196 188 ) 197 AltList pruned;198 pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned) );199 if ( failFast && pruned.empty()) {189 AltList::iterator oldBegin = alternatives.begin(); 190 pruneAlternatives( alternatives.begin(), alternatives.end(), front_inserter( alternatives ) ); 191 if ( failFast && alternatives.begin() == oldBegin ) { 200 192 std::ostringstream stream; 201 193 AltList winners; … … 207 199 throw SemanticError( stream.str() ); 208 200 } 209 alternatives = move(pruned);201 alternatives.erase( oldBegin, alternatives.end() ); 210 202 PRINT( 211 203 std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl; … … 579 571 /// State to iteratively build a match of parameter expressions to arguments 580 572 struct ArgPack { 581 std::size_t parent; ///< Index of parent pack 582 std::unique_ptr<Expression> expr; ///< The argument stored here 583 Cost cost; ///< The cost of this argument 584 TypeEnvironment env; ///< Environment for this pack 585 AssertionSet need; ///< Assertions outstanding for this pack 586 AssertionSet have; ///< Assertions found for this pack 587 OpenVarSet openVars; ///< Open variables for this pack 588 unsigned nextArg; ///< Index of next argument in arguments list 589 unsigned tupleStart; ///< Number of tuples that start at this index 590 unsigned nextExpl; ///< Index of next exploded element 591 unsigned explAlt; ///< Index of alternative for nextExpl > 0 592 593 ArgPack() 594 : parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0), 595 tupleStart(0), nextExpl(0), explAlt(0) {} 596 597 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 573 AltList actuals; ///< Arguments included in this pack 574 TypeEnvironment env; ///< Environment for this pack 575 AssertionSet need; ///< Assertions outstanding for this pack 576 AssertionSet have; ///< Assertions found for this pack 577 OpenVarSet openVars; ///< Open variables for this pack 578 unsigned nextArg; ///< Index of next argument in arguments list 579 std::vector<Alternative> expls; ///< Exploded actuals left over from last match 580 unsigned nextExpl; ///< Index of next exploded alternative to use 581 std::vector<unsigned> tupleEls; /// Number of elements in current tuple element(s) 582 583 ArgPack(const TypeEnvironment& env, const AssertionSet& need, const AssertionSet& have, 598 584 const OpenVarSet& openVars) 599 : parent(0), expr(), cost(Cost::zero), env(env), need(need), have(have), 600 openVars(openVars), nextArg(0), tupleStart(0), nextExpl(0), explAlt(0) {} 601 602 ArgPack(std::size_t parent, Expression* expr, TypeEnvironment&& env, AssertionSet&& need, 603 AssertionSet&& have, OpenVarSet&& openVars, unsigned nextArg, 604 unsigned tupleStart = 0, Cost cost = Cost::zero, unsigned nextExpl = 0, 605 unsigned explAlt = 0 ) 606 : parent(parent), expr(expr->clone()), cost(cost), env(move(env)), need(move(need)), 607 have(move(have)), openVars(move(openVars)), nextArg(nextArg), tupleStart(tupleStart), 608 nextExpl(nextExpl), explAlt(explAlt) {} 609 610 ArgPack(const ArgPack& o, TypeEnvironment&& env, AssertionSet&& need, AssertionSet&& have, 611 OpenVarSet&& openVars, unsigned nextArg, Cost added ) 612 : parent(o.parent), expr(o.expr ? o.expr->clone() : nullptr), cost(o.cost + added), 613 env(move(env)), need(move(need)), have(move(have)), openVars(move(openVars)), 614 nextArg(nextArg), tupleStart(o.tupleStart), nextExpl(0), explAlt(0) {} 615 616 /// true iff this pack is in the middle of an exploded argument 617 bool hasExpl() const { return nextExpl > 0; } 618 619 /// Gets the list of exploded alternatives for this pack 620 const ExplodedActual& getExpl( const ExplodedArgs& args ) const { 621 return args[nextArg-1][explAlt]; 622 } 623 585 : actuals(), env(env), need(need), have(have), openVars(openVars), nextArg(0), 586 expls(), nextExpl(0), tupleEls() {} 587 588 /// Starts a new tuple expression 589 void beginTuple() { 590 if ( ! tupleEls.empty() ) ++tupleEls.back(); 591 tupleEls.push_back(0); 592 } 593 624 594 /// Ends a tuple expression, consolidating the appropriate actuals 625 void endTuple( const std::vector<ArgPack>& packs) {626 // add all expressions in tuple to list, summing cost595 void endTuple() { 596 // set up new Tuple alternative 627 597 std::list<Expression*> exprs; 628 const ArgPack* pack = this; 629 if ( expr ) { exprs.push_front( expr.release() ); } 630 while ( pack->tupleStart == 0 ) { 631 pack = &packs[pack->parent]; 632 exprs.push_front( pack->expr->clone() ); 633 cost += pack->cost; 634 } 635 // reset pack to appropriate tuple 636 expr.reset( new TupleExpr( exprs ) ); 637 tupleStart = pack->tupleStart - 1; 638 parent = pack->parent; 598 Cost cost = Cost::zero; 599 600 // transfer elements into alternative 601 for (unsigned i = 0; i < tupleEls.back(); ++i) { 602 exprs.push_front( actuals.back().expr ); 603 actuals.back().expr = nullptr; 604 cost += actuals.back().cost; 605 actuals.pop_back(); 606 } 607 tupleEls.pop_back(); 608 609 // build new alternative 610 actuals.emplace_back( new TupleExpr( exprs ), this->env, cost ); 611 } 612 613 /// Clones and adds an actual, returns this 614 ArgPack& withArg( Expression* expr, Cost cost = Cost::zero ) { 615 actuals.emplace_back( expr->clone(), this->env, cost ); 616 if ( ! tupleEls.empty() ) ++tupleEls.back(); 617 return *this; 639 618 } 640 619 }; 641 620 642 621 /// Instantiates an argument to match a formal, returns false if no results left 643 bool instantiateArgument( Type* formalType, Initializer* initializer, 644 const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart, 645 const SymTab::Indexer& indexer, unsigned nTuples = 0 ) { 622 bool instantiateArgument( Type* formalType, Initializer* initializer, 623 const std::vector< AlternativeFinder >& args, 624 std::vector<ArgPack>& results, std::vector<ArgPack>& nextResults, 625 const SymTab::Indexer& indexer ) { 646 626 if ( TupleType* tupleType = dynamic_cast<TupleType*>( formalType ) ) { 647 627 // formalType is a TupleType - group actuals into a TupleExpr 648 ++nTuples;628 for ( ArgPack& result : results ) { result.beginTuple(); } 649 629 for ( Type* type : *tupleType ) { 650 630 // xxx - dropping initializer changes behaviour from previous, but seems correct 651 if ( ! instantiateArgument( 652 type, nullptr, args, results, genStart, indexer, nTuples ) ) 631 if ( ! instantiateArgument( type, nullptr, args, results, nextResults, indexer ) ) 653 632 return false; 654 nTuples = 0; 655 } 656 // re-consititute tuples for final generation 657 for ( auto i = genStart; i < results.size(); ++i ) { 658 results[i].endTuple( results ); 659 } 633 } 634 for ( ArgPack& result : results ) { result.endTuple(); } 660 635 return true; 661 636 } else if ( TypeInstType* ttype = Tuples::isTtype( formalType ) ) { 662 637 // formalType is a ttype, consumes all remaining arguments 663 638 // xxx - mixing default arguments with variadic?? 664 665 // completed tuples; will be spliced to end of results to finish 666 std::vector<ArgPack> finalResults{}; 667 639 std::vector<ArgPack> finalResults{}; /// list of completed tuples 640 // start tuples 641 for ( ArgPack& result : results ) { 642 result.beginTuple(); 643 644 // use rest of exploded tuple if present 645 while ( result.nextExpl < result.expls.size() ) { 646 const Alternative& actual = result.expls[result.nextExpl]; 647 result.env.addActual( actual.env, result.openVars ); 648 result.withArg( actual.expr ); 649 ++result.nextExpl; 650 } 651 } 668 652 // iterate until all results completed 669 std::size_t genEnd; 670 ++nTuples; 671 do { 672 genEnd = results.size(); 673 653 while ( ! results.empty() ) { 674 654 // add another argument to results 675 for ( std::size_t i = genStart; i < genEnd; ++i) {676 auto nextArg = results[i].nextArg;677 678 // use remainder of exploded tuple if present679 if ( results[i].hasExpl() ) {680 const ExplodedActual& expl = results[i].getExpl( args );681 const Alternative& actual = expl.alts[results[i].nextExpl];682 683 TypeEnvironment env = results[i].env;684 OpenVarSet openVars = results[i].openVars;685 686 env.addActual( actual.env, openVars);687 688 unsigned nextExpl = results[i].nextExpl + 1;689 if ( nextExpl == expl.alts.size() ) {690 nextExpl = 0;655 for ( ArgPack& result : results ) { 656 // finish result when out of arguments 657 if ( result.nextArg >= args.size() ) { 658 Type* argType = result.actuals.back().expr->get_result(); 659 if ( result.tupleEls.back() == 1 && Tuples::isTtype( argType ) ) { 660 // the case where a ttype value is passed directly is special, e.g. for 661 // argument forwarding purposes 662 // xxx - what if passing multiple arguments, last of which is ttype? 663 // xxx - what would happen if unify was changed so that unifying tuple 664 // types flattened both before unifying lists? then pass in TupleType 665 // (ttype) below. 666 result.tupleEls.pop_back(); 667 } else { 668 // collapse leftover arguments into tuple 669 result.endTuple(); 670 argType = result.actuals.back().expr->get_result(); 691 671 } 692 693 results.emplace_back( 694 i, actual.expr, move(env), copy(results[i].need), 695 copy(results[i].have), move(openVars), nextArg, nTuples, 696 Cost::zero, nextExpl, results[i].explAlt ); 697 672 // check unification for ttype before adding to final 673 if ( unify( ttype, argType, result.env, result.need, result.have, 674 result.openVars, indexer ) ) { 675 finalResults.push_back( std::move(result) ); 676 } 698 677 continue; 699 678 } 700 701 // finish result when out of arguments 702 if ( nextArg >= args.size() ) { 703 ArgPack newResult{ 704 results[i].env, results[i].need, results[i].have, 705 results[i].openVars }; 706 newResult.nextArg = nextArg; 707 Type* argType; 708 709 if ( nTuples > 0 ) { 710 // first iteration, push empty tuple expression 711 newResult.parent = i; 712 std::list<Expression*> emptyList; 713 newResult.expr.reset( new TupleExpr( emptyList ) ); 714 argType = newResult.expr->get_result(); 715 } else { 716 // clone result to collect tuple 717 newResult.parent = results[i].parent; 718 newResult.cost = results[i].cost; 719 newResult.tupleStart = results[i].tupleStart; 720 newResult.expr.reset( results[i].expr->clone() ); 721 argType = newResult.expr->get_result(); 722 723 if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) { 724 // the case where a ttype value is passed directly is special, 725 // e.g. for argument forwarding purposes 726 // xxx - what if passing multiple arguments, last of which is 727 // ttype? 728 // xxx - what would happen if unify was changed so that unifying 729 // tuple 730 // types flattened both before unifying lists? then pass in 731 // TupleType (ttype) below. 732 --newResult.tupleStart; 733 } else { 734 // collapse leftover arguments into tuple 735 newResult.endTuple( results ); 736 argType = newResult.expr->get_result(); 737 } 679 680 // add each possible next argument 681 for ( const Alternative& actual : args[result.nextArg] ) { 682 ArgPack aResult = result; // copy to clone everything 683 // add details of actual to result 684 aResult.env.addActual( actual.env, aResult.openVars ); 685 Cost cost = actual.cost; 686 687 // explode argument 688 std::vector<Alternative> exploded; 689 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 690 691 // add exploded argument to tuple 692 for ( Alternative& aActual : exploded ) { 693 aResult.withArg( aActual.expr, cost ); 694 cost = Cost::zero; 738 695 } 739 740 // check unification for ttype before adding to final 741 if ( unify( ttype, argType, newResult.env, newResult.need, newResult.have, 742 newResult.openVars, indexer ) ) { 743 finalResults.push_back( move(newResult) ); 744 } 745 746 continue; 696 ++aResult.nextArg; 697 nextResults.push_back( std::move(aResult) ); 747 698 } 748 749 // add each possible next argument750 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {751 const ExplodedActual& expl = args[nextArg][j];752 753 // fresh copies of parent parameters for this iteration754 TypeEnvironment env = results[i].env;755 OpenVarSet openVars = results[i].openVars;756 757 env.addActual( expl.env, openVars );758 759 // skip empty tuple arguments by (near-)cloning parent into next gen760 if ( expl.alts.empty() ) {761 results.emplace_back(762 results[i], move(env), copy(results[i].need),763 copy(results[i].have), move(openVars), nextArg + 1, expl.cost );764 765 continue;766 }767 768 // add new result769 results.emplace_back(770 i, expl.alts.front().expr, move(env), copy(results[i].need),771 copy(results[i].have), move(openVars), nextArg + 1,772 nTuples, expl.cost, expl.alts.size() == 1 ? 0 : 1, j );773 }774 699 } 775 700 776 701 // reset for next round 777 genStart = genEnd; 778 nTuples = 0; 779 } while ( genEnd != results.size() ); 780 781 // splice final results onto results 782 for ( std::size_t i = 0; i < finalResults.size(); ++i ) { 783 results.push_back( move(finalResults[i]) ); 784 } 785 return ! finalResults.empty(); 702 results.swap( nextResults ); 703 nextResults.clear(); 704 } 705 results.swap( finalResults ); 706 return ! results.empty(); 786 707 } 787 708 788 709 // iterate each current subresult 789 std::size_t genEnd = results.size(); 790 for ( std::size_t i = genStart; i < genEnd; ++i ) { 791 auto nextArg = results[i].nextArg; 792 793 // use remainder of exploded tuple if present 794 if ( results[i].hasExpl() ) { 795 const ExplodedActual& expl = results[i].getExpl( args ); 796 const Alternative& actual = expl.alts[results[i].nextExpl]; 797 798 TypeEnvironment env = results[i].env; 799 AssertionSet need = results[i].need, have = results[i].have; 800 OpenVarSet openVars = results[i].openVars; 801 802 env.addActual( actual.env, openVars ); 710 for ( unsigned iResult = 0; iResult < results.size(); ++iResult ) { 711 ArgPack& result = results[iResult]; 712 713 if ( result.nextExpl < result.expls.size() ) { 714 // use remainder of exploded tuple if present 715 const Alternative& actual = result.expls[result.nextExpl]; 716 result.env.addActual( actual.env, result.openVars ); 803 717 Type* actualType = actual.expr->get_result(); 804 718 … … 810 724 std::cerr << std::endl; 811 725 ) 812 813 if ( unify( formalType, actualType, env, need, have, openVars, indexer ) ) { 814 unsigned nextExpl = results[i].nextExpl + 1; 815 if ( nextExpl == expl.alts.size() ) { 816 nextExpl = 0; 817 } 818 819 results.emplace_back( 820 i, actual.expr, move(env), move(need), move(have), move(openVars), 821 nextArg, nTuples, Cost::zero, nextExpl, results[i].explAlt ); 726 727 if ( unify( formalType, actualType, result.env, result.need, result.have, 728 result.openVars, indexer ) ) { 729 ++result.nextExpl; 730 nextResults.push_back( std::move(result.withArg( actual.expr )) ); 822 731 } 823 732 824 733 continue; 825 } 826 827 // use default initializers if out of arguments 828 if ( nextArg >= args.size() ) { 734 } else if ( result.nextArg >= args.size() ) { 735 // use default initializers if out of arguments 829 736 if ( ConstantExpr* cnstExpr = getDefaultValue( initializer ) ) { 830 737 if ( Constant* cnst = dynamic_cast<Constant*>( cnstExpr->get_constant() ) ) { 831 TypeEnvironment env = results[i].env; 832 AssertionSet need = results[i].need, have = results[i].have; 833 OpenVarSet openVars = results[i].openVars; 834 835 if ( unify( formalType, cnst->get_type(), env, need, have, openVars, 836 indexer ) ) { 837 results.emplace_back( 838 i, cnstExpr, move(env), move(need), move(have), 839 move(openVars), nextArg, nTuples ); 738 if ( unify( formalType, cnst->get_type(), result.env, result.need, 739 result.have, result.openVars, indexer ) ) { 740 nextResults.push_back( std::move(result.withArg( cnstExpr )) ); 840 741 } 841 742 } 842 743 } 843 844 744 continue; 845 745 } 846 746 847 747 // Check each possible next argument 848 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 849 const ExplodedActual& expl = args[nextArg][j]; 850 851 // fresh copies of parent parameters for this iteration 852 TypeEnvironment env = results[i].env; 853 AssertionSet need = results[i].need, have = results[i].have; 854 OpenVarSet openVars = results[i].openVars; 855 856 env.addActual( expl.env, openVars ); 857 858 // skip empty tuple arguments by (near-)cloning parent into next gen 859 if ( expl.alts.empty() ) { 860 results.emplace_back( 861 results[i], move(env), move(need), move(have), move(openVars), 862 nextArg + 1, expl.cost ); 863 748 for ( const Alternative& actual : args[result.nextArg] ) { 749 ArgPack aResult = result; // copy to clone everything 750 // add details of actual to result 751 aResult.env.addActual( actual.env, aResult.openVars ); 752 753 // explode argument 754 std::vector<Alternative> exploded; 755 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 756 if ( exploded.empty() ) { 757 // skip empty tuple arguments 758 ++aResult.nextArg; 759 results.push_back( std::move(aResult) ); 864 760 continue; 865 761 } 866 762 867 763 // consider only first exploded actual 868 const Alternative& a ctual = expl.alts.front();869 Type* actualType = a ctual.expr->get_result()->clone();764 const Alternative& aActual = exploded.front(); 765 Type* actualType = aActual.expr->get_result()->clone(); 870 766 871 767 PRINT( … … 878 774 879 775 // attempt to unify types 880 if ( unify( formalType, actualType, env, need, have, openVars, indexer ) ) { 881 // add new result 882 results.emplace_back( 883 i, actual.expr, move(env), move(need), move(have), move(openVars), 884 nextArg + 1, nTuples, expl.cost, expl.alts.size() == 1 ? 0 : 1, j ); 776 if ( unify( formalType, actualType, aResult.env, aResult.need, aResult.have, aResult.openVars, indexer ) ) { 777 // add argument 778 aResult.withArg( aActual.expr, actual.cost ); 779 ++aResult.nextArg; 780 if ( exploded.size() > 1 ) { 781 // other parts of tuple left over 782 aResult.expls = std::move( exploded ); 783 aResult.nextExpl = 1; 784 } 785 nextResults.push_back( std::move(aResult) ); 885 786 } 886 787 } … … 888 789 889 790 // reset for next parameter 890 genStart = genEnd; 891 892 return genEnd != results.size(); 893 } 894 895 template<typename OutputIterator> 896 void AlternativeFinder::validateFunctionAlternative( const Alternative &func, ArgPack& result, 897 const std::vector<ArgPack>& results, OutputIterator out ) { 898 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); 899 // sum cost and accumulate actuals 900 std::list<Expression*>& args = appExpr->get_args(); 901 Cost cost = Cost::zero; 902 const ArgPack* pack = &result; 903 while ( pack->expr ) { 904 args.push_front( pack->expr->clone() ); 905 cost += pack->cost; 906 pack = &results[pack->parent]; 907 } 908 // build and validate new alternative 909 Alternative newAlt( appExpr, result.env, cost ); 910 PRINT( 911 std::cerr << "instantiate function success: " << appExpr << std::endl; 912 std::cerr << "need assertions:" << std::endl; 913 printAssertionSet( result.need, std::cerr, 8 ); 914 ) 915 inferParameters( result.need, result.have, newAlt, result.openVars, out ); 791 results.swap( nextResults ); 792 nextResults.clear(); 793 794 return ! results.empty(); 916 795 } 917 796 918 797 template<typename OutputIterator> 919 798 void AlternativeFinder::makeFunctionAlternatives( const Alternative &func, 920 FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) { 799 FunctionType *funcType, const std::vector< AlternativeFinder > &args, 800 OutputIterator out ) { 921 801 OpenVarSet funcOpenVars; 922 802 AssertionSet funcNeed, funcHave; … … 938 818 939 819 // iteratively build matches, one parameter at a time 940 std::vector<ArgPack> results; 941 results.push_back( ArgPack{ funcEnv, funcNeed, funcHave, funcOpenVars } ); 942 std::size_t genStart = 0; 943 820 std::vector<ArgPack> results{ ArgPack{ funcEnv, funcNeed, funcHave, funcOpenVars } }; 821 std::vector<ArgPack> nextResults{}; 944 822 for ( DeclarationWithType* formal : funcType->get_parameters() ) { 945 823 ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal ); 946 if ( ! instantiateArgument( 947 obj->get_type(), obj->get_init(), args, results, genStart, indexer ) )824 if ( ! instantiateArgument( 825 obj->get_type(), obj->get_init(), args, results, nextResults, indexer ) ) 948 826 return; 949 827 } 950 828 829 // filter out results that don't use all the arguments, and aren't variadic 830 std::vector<ArgPack> finalResults{}; 951 831 if ( funcType->get_isVarArgs() ) { 952 // append any unused arguments to vararg pack 953 std::size_t genEnd; 954 do { 955 genEnd = results.size(); 956 957 // iterate results 958 for ( std::size_t i = genStart; i < genEnd; ++i ) { 959 auto nextArg = results[i].nextArg; 960 961 // use remainder of exploded tuple if present 962 if ( results[i].hasExpl() ) { 963 const ExplodedActual& expl = results[i].getExpl( args ); 964 const Alternative& actual = expl.alts[results[i].nextExpl]; 965 966 TypeEnvironment env = results[i].env; 967 OpenVarSet openVars = results[i].openVars; 968 969 env.addActual( actual.env, openVars ); 970 971 unsigned nextExpl = results[i].nextExpl + 1; 972 if ( nextExpl == expl.alts.size() ) { 973 nextExpl = 0; 974 } 975 976 results.emplace_back( 977 i, actual.expr, move(env), copy(results[i].need), 978 copy(results[i].have), move(openVars), nextArg, 0, 979 Cost::zero, nextExpl, results[i].explAlt ); 980 832 for ( ArgPack& result : results ) { 833 // use rest of exploded tuple if present 834 while ( result.nextExpl < result.expls.size() ) { 835 const Alternative& actual = result.expls[result.nextExpl]; 836 result.env.addActual( actual.env, result.openVars ); 837 result.withArg( actual.expr ); 838 ++result.nextExpl; 839 } 840 } 841 842 while ( ! results.empty() ) { 843 // build combinations for all remaining arguments 844 for ( ArgPack& result : results ) { 845 // keep if used all arguments 846 if ( result.nextArg >= args.size() ) { 847 finalResults.push_back( std::move(result) ); 981 848 continue; 982 849 } 983 850 984 // finish result when out of arguments 985 if ( nextArg >= args.size() ) { 986 validateFunctionAlternative( func, results[i], results, out ); 987 988 continue; 851 // add each possible next argument 852 for ( const Alternative& actual : args[result.nextArg] ) { 853 ArgPack aResult = result; // copy to clone everything 854 // add details of actual to result 855 aResult.env.addActual( actual.env, aResult.openVars ); 856 Cost cost = actual.cost; 857 858 // explode argument 859 std::vector<Alternative> exploded; 860 Tuples::explode( actual, indexer, back_inserter( exploded ) ); 861 862 // add exploded argument to arg list 863 for ( Alternative& aActual : exploded ) { 864 aResult.withArg( aActual.expr, cost ); 865 cost = Cost::zero; 866 } 867 ++aResult.nextArg; 868 nextResults.push_back( std::move(aResult) ); 989 869 } 990 991 // add each possible next argument 992 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 993 const ExplodedActual& expl = args[nextArg][j]; 994 995 // fresh copies of parent parameters for this iteration 996 TypeEnvironment env = results[i].env; 997 OpenVarSet openVars = results[i].openVars; 998 999 env.addActual( expl.env, openVars ); 1000 1001 // skip empty tuple arguments by (near-)cloning parent into next gen 1002 if ( expl.alts.empty() ) { 1003 results.emplace_back( 1004 results[i], move(env), copy(results[i].need), 1005 copy(results[i].have), move(openVars), nextArg + 1, expl.cost ); 1006 1007 continue; 1008 } 1009 1010 // add new result 1011 results.emplace_back( 1012 i, expl.alts.front().expr, move(env), copy(results[i].need), 1013 copy(results[i].have), move(openVars), nextArg + 1, 0, 1014 expl.cost, expl.alts.size() == 1 ? 0 : 1, j ); 1015 } 1016 } 1017 1018 genStart = genEnd; 1019 } while ( genEnd != results.size() ); 870 } 871 872 // reset for next round 873 results.swap( nextResults ); 874 nextResults.clear(); 875 } 1020 876 } else { 1021 877 // filter out results that don't use all the arguments 1022 for ( std::size_t i = genStart; i < results.size(); ++i ) { 1023 ArgPack& result = results[i]; 1024 if ( ! result.hasExpl() && result.nextArg >= args.size() ) { 1025 validateFunctionAlternative( func, result, results, out ); 1026 } 1027 } 878 for ( ArgPack& result : results ) { 879 if ( result.nextExpl >= result.expls.size() && result.nextArg >= args.size() ) { 880 finalResults.push_back( std::move(result) ); 881 } 882 } 883 } 884 885 // validate matching combos, add to final result list 886 for ( ArgPack& result : finalResults ) { 887 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); 888 Alternative newAlt( appExpr, result.env, sumCost( result.actuals ) ); 889 makeExprList( result.actuals, appExpr->get_args() ); 890 PRINT( 891 std::cerr << "instantiate function success: " << appExpr << std::endl; 892 std::cerr << "need assertions:" << std::endl; 893 printAssertionSet( result.need, std::cerr, 8 ); 894 ) 895 inferParameters( result.need, result.have, newAlt, result.openVars, out ); 1028 896 } 1029 897 } … … 1052 920 printAlts( funcOpFinder.alternatives, std::cerr, 1 ); 1053 921 ) 1054 1055 // pre-explode arguments1056 ExplodedArgs argExpansions;1057 argExpansions.reserve( argAlternatives.size() );1058 1059 for ( const AlternativeFinder& arg : argAlternatives ) {1060 argExpansions.emplace_back();1061 auto& argE = argExpansions.back();1062 argE.reserve( arg.alternatives.size() );1063 1064 for ( const Alternative& actual : arg ) {1065 argE.emplace_back( actual, indexer );1066 }1067 }1068 922 1069 923 AltList candidates; … … 1080 934 Alternative newFunc( *func ); 1081 935 referenceToRvalueConversion( newFunc.expr ); 1082 makeFunctionAlternatives( newFunc, function, arg Expansions,936 makeFunctionAlternatives( newFunc, function, argAlternatives, 1083 937 std::back_inserter( candidates ) ); 1084 938 } … … 1089 943 Alternative newFunc( *func ); 1090 944 referenceToRvalueConversion( newFunc.expr ); 1091 makeFunctionAlternatives( newFunc, function, arg Expansions,945 makeFunctionAlternatives( newFunc, function, argAlternatives, 1092 946 std::back_inserter( candidates ) ); 1093 947 } // if … … 1101 955 // try each function operator ?() with each function alternative 1102 956 if ( ! funcOpFinder.alternatives.empty() ) { 1103 // add exploded function alternatives to front of argument list 1104 std::vector<ExplodedActual> funcE; 1105 funcE.reserve( funcFinder.alternatives.size() ); 1106 for ( const Alternative& actual : funcFinder ) { 1107 funcE.emplace_back( actual, indexer ); 1108 } 1109 argExpansions.insert( argExpansions.begin(), move(funcE) ); 957 // add function alternatives to front of argument list 958 argAlternatives.insert( argAlternatives.begin(), std::move(funcFinder) ); 1110 959 1111 960 for ( AltList::iterator funcOp = funcOpFinder.alternatives.begin(); … … 1119 968 Alternative newFunc( *funcOp ); 1120 969 referenceToRvalueConversion( newFunc.expr ); 1121 makeFunctionAlternatives( newFunc, function, arg Expansions,970 makeFunctionAlternatives( newFunc, function, argAlternatives, 1122 971 std::back_inserter( candidates ) ); 1123 972 } … … 1133 982 1134 983 // compute conversionsion costs 1135 for ( Alt ernative& withFunc : candidates) {1136 Cost cvtCost = computeApplicationConversionCost( withFunc, indexer );984 for ( AltList::iterator withFunc = candidates.begin(); withFunc != candidates.end(); ++withFunc ) { 985 Cost cvtCost = computeApplicationConversionCost( *withFunc, indexer ); 1137 986 1138 987 PRINT( 1139 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( withFunc .expr );988 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( withFunc->expr ); 1140 989 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 1141 990 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() ); … … 1146 995 printAll( appExpr->get_args(), std::cerr, 8 ); 1147 996 std::cerr << "bindings are:" << std::endl; 1148 withFunc .env.print( std::cerr, 8 );997 withFunc->env.print( std::cerr, 8 ); 1149 998 std::cerr << "cost of conversion is:" << cvtCost << std::endl; 1150 999 ) 1151 1000 if ( cvtCost != Cost::infinity ) { 1152 withFunc .cvtCost = cvtCost;1153 alternatives.push_back( withFunc );1001 withFunc->cvtCost = cvtCost; 1002 alternatives.push_back( *withFunc ); 1154 1003 } // if 1155 1004 } // for 1156 1005 1157 candidates = move(alternatives); 1006 candidates.clear(); 1007 candidates.splice( candidates.end(), alternatives ); 1158 1008 1159 1009 // use a new list so that alternatives are not examined by addAnonConversions twice. … … 1161 1011 findMinCost( candidates.begin(), candidates.end(), std::back_inserter( winners ) ); 1162 1012 1163 // function may return struct or union value, in which case we need to add alternatives 1164 // for implicitconversions to each of the anonymous members, must happen after findMinCost1165 // since anon conversionsare never the cheapest expression1013 // function may return struct or union value, in which case we need to add alternatives for implicit 1014 // conversions to each of the anonymous members, must happen after findMinCost since anon conversions 1015 // are never the cheapest expression 1166 1016 for ( const Alternative & alt : winners ) { 1167 1017 addAnonConversions( alt ); 1168 1018 } 1169 spliceBegin( alternatives, winners );1019 alternatives.splice( alternatives.begin(), winners ); 1170 1020 1171 1021 if ( alternatives.empty() && targetType && ! targetType->isVoid() ) { … … 1191 1041 AlternativeFinder finder( indexer, env ); 1192 1042 finder.find( addressExpr->get_arg() ); 1193 for ( Alternative& alt : finder.alternatives ) { 1194 if ( isLvalue( alt.expr ) ) { 1195 alternatives.push_back( 1196 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } ); 1043 for ( std::list< Alternative >::iterator i = finder.alternatives.begin(); i != finder.alternatives.end(); ++i ) { 1044 if ( isLvalue( i->expr ) ) { 1045 alternatives.push_back( Alternative( new AddressExpr( i->expr->clone() ), i->env, i->cost ) ); 1197 1046 } // if 1198 1047 } // for … … 1200 1049 1201 1050 void AlternativeFinder::visit( LabelAddressExpr * expr ) { 1202 alternatives.push_back( Alternative { expr->clone(), env, Cost::zero });1051 alternatives.push_back( Alternative( expr->clone(), env, Cost::zero) ); 1203 1052 } 1204 1053 … … 1242 1091 1243 1092 AltList candidates; 1244 for ( Alternative& alt : finder.alternatives) {1093 for ( std::list< Alternative >::iterator i = finder.alternatives.begin(); i != finder.alternatives.end(); ++i ) { 1245 1094 AssertionSet needAssertions, haveAssertions; 1246 1095 OpenVarSet openVars; … … 1250 1099 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1251 1100 // to. 1252 int discardedValues = alt.expr->get_result()->size() - castExpr->get_result()->size();1101 int discardedValues = i->expr->get_result()->size() - castExpr->get_result()->size(); 1253 1102 if ( discardedValues < 0 ) continue; 1254 1103 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1255 1104 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1256 1105 // unification run for side-effects 1257 unify( castExpr->get_result(), alt.expr->get_result(), alt.env, needAssertions, 1258 haveAssertions, openVars, indexer ); 1259 Cost thisCost = castCost( alt.expr->get_result(), castExpr->get_result(), indexer, 1260 alt.env ); 1106 unify( castExpr->get_result(), i->expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer ); 1107 Cost thisCost = castCost( i->expr->get_result(), castExpr->get_result(), indexer, i->env ); 1261 1108 if ( thisCost != Cost::infinity ) { 1262 1109 // count one safe conversion for each value that is thrown away 1263 1110 thisCost.incSafe( discardedValues ); 1264 Alternative newAlt( restructureCast( alt.expr->clone(), toType ), alt.env, 1265 alt.cost, thisCost ); 1266 inferParameters( needAssertions, haveAssertions, newAlt, openVars, 1267 back_inserter( candidates ) ); 1111 Alternative newAlt( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ); 1112 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 1268 1113 } // if 1269 1114 } // for … … 1552 1397 1553 1398 void AlternativeFinder::visit( UntypedTupleExpr *tupleExpr ) { 1554 std::vector< AlternativeFinder > subExprAlternatives; 1555 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), 1556 back_inserter( subExprAlternatives ) ); 1557 std::vector< AltList > possibilities; 1558 combos( subExprAlternatives.begin(), subExprAlternatives.end(), 1559 back_inserter( possibilities ) ); 1560 for ( const AltList& alts : possibilities ) { 1399 std::list< AlternativeFinder > subExprAlternatives; 1400 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), back_inserter( subExprAlternatives ) ); 1401 std::list< AltList > possibilities; 1402 combos( subExprAlternatives.begin(), subExprAlternatives.end(), back_inserter( possibilities ) ); 1403 for ( std::list< AltList >::const_iterator i = possibilities.begin(); i != possibilities.end(); ++i ) { 1561 1404 std::list< Expression * > exprs; 1562 makeExprList( alts, exprs );1405 makeExprList( *i, exprs ); 1563 1406 1564 1407 TypeEnvironment compositeEnv; 1565 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1566 alternatives.push_back( 1567 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 1408 simpleCombineEnvironments( i->begin(), i->end(), compositeEnv ); 1409 alternatives.push_back( Alternative( new TupleExpr( exprs ) , compositeEnv, sumCost( *i ) ) ); 1568 1410 } // for 1569 1411 } -
src/ResolvExpr/AlternativeFinder.h
r88ef2af r9f10d1f2 21 21 22 22 #include "Alternative.h" // for AltList, Alternative 23 #include "ExplodedActual.h" // for ExplodedActual24 23 #include "ResolvExpr/Cost.h" // for Cost, Cost::infinity 25 24 #include "ResolvExpr/TypeEnvironment.h" // for AssertionSet, OpenVarSet … … 32 31 33 32 namespace ResolvExpr { 34 class ArgPack;35 36 /// First index is which argument, second index is which alternative for that argument,37 /// third index is which exploded element of that alternative38 using ExplodedArgs = std::vector< std::vector< ExplodedActual > >;39 40 33 class AlternativeFinder : public Visitor { 41 34 public: … … 133 126 /// Adds alternatives for offsetof expressions, given the base type and name of the member 134 127 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); 135 /// Takes a final result and checks if its assertions can be satisfied136 128 template<typename OutputIterator> 137 void validateFunctionAlternative( const Alternative &func, ArgPack& result, const std::vector<ArgPack>& results, OutputIterator out ); 138 /// Finds matching alternatives for a function, given a set of arguments 139 template<typename OutputIterator> 140 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out ); 141 /// Checks if assertion parameters match for a new alternative 129 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const std::vector< AlternativeFinder >& args, OutputIterator out ); 142 130 template< typename OutputIterator > 143 131 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ); -
src/ResolvExpr/Resolver.cc
r88ef2af r9f10d1f2 18 18 #include <memory> // for allocator, allocator_traits<... 19 19 #include <tuple> // for get 20 #include <vector>21 20 22 21 #include "Alternative.h" // for Alternative, AltList … … 412 411 413 412 // Find all alternatives for all arguments in canonical form 414 std:: vector< AlternativeFinder > argAlternatives;413 std::list< AlternativeFinder > argAlternatives; 415 414 funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) ); 416 415 417 416 // List all combinations of arguments 418 std:: vector< AltList > possibilities;417 std::list< AltList > possibilities; 419 418 combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) ); 420 419 -
src/ResolvExpr/module.mk
r88ef2af r9f10d1f2 32 32 ResolvExpr/Occurs.cc \ 33 33 ResolvExpr/TypeEnvironment.cc \ 34 ResolvExpr/CurrentObject.cc \ 35 ResolvExpr/ExplodedActual.cc 34 ResolvExpr/CurrentObject.cc -
src/ResolvExpr/typeops.h
r88ef2af r9f10d1f2 16 16 #pragma once 17 17 18 #include <vector>19 20 18 #include "SynTree/SynTree.h" 21 19 #include "SynTree/Type.h" … … 30 28 void combos( InputIterator begin, InputIterator end, OutputIterator out ) { 31 29 typedef typename InputIterator::value_type SetType; 32 typedef typename std:: vector< typename SetType::value_type > ListType;30 typedef typename std::list< typename SetType::value_type > ListType; 33 31 34 32 if ( begin == end ) { … … 40 38 begin++; 41 39 42 std:: vector< ListType > recursiveResult;40 std::list< ListType > recursiveResult; 43 41 combos( begin, end, back_inserter( recursiveResult ) ); 44 42 45 for ( const auto& i : recursiveResult ) for ( const auto& j : *current ) { 46 ListType result; 47 std::back_insert_iterator< ListType > inserter = back_inserter( result ); 48 *inserter++ = j; 49 std::copy( i.begin(), i.end(), inserter ); 50 *out++ = result; 51 } 43 for ( typename std::list< ListType >::const_iterator i = recursiveResult.begin(); i != recursiveResult.end(); ++i ) { 44 for ( typename ListType::const_iterator j = current->begin(); j != current->end(); ++j ) { 45 ListType result; 46 std::back_insert_iterator< ListType > inserter = back_inserter( result ); 47 *inserter++ = *j; 48 std::copy( i->begin(), i->end(), inserter ); 49 *out++ = result; 50 } // for 51 } // for 52 52 } 53 53 -
src/SymTab/Validate.cc
r88ef2af r9f10d1f2 423 423 } 424 424 425 void checkGenericParameters( ReferenceToType * inst ) {426 for ( Expression * param : inst->parameters ) {427 if ( ! dynamic_cast< TypeExpr * >( param ) ) {428 throw SemanticError( "Expression parameters for generic types are currently unsupported: ", inst );429 }430 }431 }432 433 425 void LinkReferenceToTypes::postvisit( StructInstType *structInst ) { 434 426 StructDecl *st = local_indexer->lookupStruct( structInst->get_name() ); … … 442 434 forwardStructs[ structInst->get_name() ].push_back( structInst ); 443 435 } // if 444 checkGenericParameters( structInst );445 436 } 446 437 … … 455 446 forwardUnions[ unionInst->get_name() ].push_back( unionInst ); 456 447 } // if 457 checkGenericParameters( unionInst );458 448 } 459 449 … … 535 525 // need to carry over the 'sized' status of each decl in the instance 536 526 for ( auto p : group_iterate( traitDecl->get_parameters(), traitInst->get_parameters() ) ) { 537 TypeExpr * expr = dynamic_cast< TypeExpr * >( std::get<1>(p) ); 538 if ( ! expr ) { 539 throw SemanticError( "Expression parameters for trait instances are currently unsupported: ", std::get<1>(p) ); 540 } 527 TypeExpr * expr = strict_dynamic_cast< TypeExpr * >( std::get<1>(p) ); 541 528 if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( expr->get_type() ) ) { 542 529 TypeDecl * formalDecl = std::get<0>(p); -
src/Tuples/TupleAssignment.cc
r88ef2af r9f10d1f2 251 251 // combine assignment environments into combined expression environment 252 252 simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv ); 253 // xxx -- was push_front 254 currentFinder.get_alternatives().push_back( ResolvExpr::Alternative( 253 currentFinder.get_alternatives().push_front( ResolvExpr::Alternative( 255 254 new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv, 256 255 ResolvExpr::sumCost( current ) + matcher->baseCost ) ); -
src/tests/.expect/castError.txt
r88ef2af r9f10d1f2 5 5 charAlternatives are: 6 6 Cost ( 1, 0, 0, 0 ): Cast of: 7 Variable Expression: f: function 8 accepting unspecified arguments 9 ... returning nothing 10 7 Variable Expression: f: signed int 11 8 ... to: 12 9 char … … 26 23 27 24 Cost ( 1, 0, 0, 0 ): Cast of: 28 Variable Expression: f: signed int 25 Variable Expression: f: function 26 accepting unspecified arguments 27 ... returning nothing 28 29 29 ... to: 30 30 char
Note:
See TracChangeset
for help on using the changeset viewer.