Changeset 276a55b2
- Timestamp:
- Jan 14, 2019, 3:38:28 PM (5 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, no_list, persistent-indexer, pthread-emulation, qualifiedEnum
- Children:
- fd73248
- Parents:
- 07ec1a2 (diff), 52ffa30 (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. - Files:
-
- 5 added
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Common/utility.h
r07ec1a2 r276a55b2 26 26 #include <string> 27 27 #include <type_traits> 28 #include <utility> 28 29 29 30 #include <cassert> … … 462 463 std::pair<long long int, bool> eval(Expression * expr); 463 464 465 // ----------------------------------------------------------------------------- 466 /// Reorders the input range in-place so that the minimal-value elements according to the 467 /// comparator are in front; 468 /// returns the iterator after the last minimal-value element. 469 template<typename Iter, typename Compare> 470 Iter sort_mins( Iter begin, Iter end, Compare& lt ) { 471 if ( begin == end ) return end; 472 473 Iter min_pos = begin; 474 for ( Iter i = begin + 1; i != end; ++i ) { 475 if ( lt( *i, *min_pos ) ) { 476 // new minimum cost; swap into first position 477 min_pos = begin; 478 std::iter_swap( min_pos, i ); 479 } else if ( ! lt( *min_pos, *i ) ) { 480 // duplicate minimum cost; swap into next minimum position 481 ++min_pos; 482 std::iter_swap( min_pos, i ); 483 } 484 } 485 return ++min_pos; 486 } 487 488 template<typename Iter, typename Compare> 489 inline Iter sort_mins( Iter begin, Iter end, Compare&& lt ) { 490 return sort_mins( begin, end, lt ); 491 } 492 493 /// sort_mins defaulted to use std::less 494 template<typename Iter> 495 inline Iter sort_mins( Iter begin, Iter end ) { 496 return sort_mins( begin, end, std::less<typename std::iterator_traits<Iter>::value_type>{} ); 497 } 498 464 499 // Local Variables: // 465 500 // tab-width: 4 // -
src/GenPoly/Box.cc
r07ec1a2 r276a55b2 798 798 for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) { 799 799 for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->assertions.begin(); assert != (*tyVar)->assertions.end(); ++assert ) { 800 InferredParams::const_iterator inferParam = appExpr-> get_inferParams().find( (*assert)->get_uniqueId() );801 assertf( inferParam != appExpr-> get_inferParams().end(), "addInferredParams missing inferred parameter: %s in: %s", toString( *assert ).c_str(), toString( appExpr ).c_str() );800 InferredParams::const_iterator inferParam = appExpr->inferParams.find( (*assert)->get_uniqueId() ); 801 assertf( inferParam != appExpr->inferParams.end(), "addInferredParams missing inferred parameter: %s in: %s", toString( *assert ).c_str(), toString( appExpr ).c_str() ); 802 802 Expression *newExpr = inferParam->second.expr->clone(); 803 803 addCast( newExpr, (*assert)->get_type(), tyVars ); -
src/GenPoly/Specialize.cc
r07ec1a2 r276a55b2 245 245 appExpr->env = TypeSubstitution::newFromExpr( appExpr, env ); 246 246 if ( inferParams ) { 247 appExpr-> get_inferParams()= *inferParams;247 appExpr->inferParams = *inferParams; 248 248 } // if 249 249 … … 284 284 std::list< Expression* >::iterator actual; 285 285 for ( formal = function->get_parameters().begin(), actual = appExpr->get_args().begin(); formal != function->get_parameters().end() && actual != appExpr->get_args().end(); ++formal, ++actual ) { 286 *actual = doSpecialization( (*formal)->get_type(), *actual, &appExpr-> get_inferParams());286 *actual = doSpecialization( (*formal)->get_type(), *actual, &appExpr->inferParams ); 287 287 } 288 288 } … … 295 295 // alternatively, if order starts to matter then copy appExpr's inferParams and pass them to handleExplicitParams. 296 296 handleExplicitParams( appExpr ); 297 for ( InferredParams::iterator inferParam = appExpr-> get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) {298 inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, inferParam->second.inferParams.get());297 for ( InferredParams::iterator inferParam = appExpr->inferParams.begin(); inferParam != appExpr->inferParams.end(); ++inferParam ) { 298 inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &inferParam->second.expr->inferParams ); 299 299 } 300 300 } -
src/Makefile.am
r07ec1a2 r276a55b2 127 127 ResolvExpr/PtrsCastable.cc \ 128 128 ResolvExpr/RenameVars.cc \ 129 ResolvExpr/ResolveAssertions.cc \ 129 130 ResolvExpr/Resolver.cc \ 130 131 ResolvExpr/ResolveTypeof.cc \ 132 ResolvExpr/SpecCost.cc \ 131 133 ResolvExpr/TypeEnvironment.cc \ 132 134 ResolvExpr/Unify.cc \ -
src/Makefile.in
r07ec1a2 r276a55b2 206 206 ResolvExpr/PtrsAssignable.$(OBJEXT) \ 207 207 ResolvExpr/PtrsCastable.$(OBJEXT) \ 208 ResolvExpr/RenameVars.$(OBJEXT) ResolvExpr/Resolver.$(OBJEXT) \ 208 ResolvExpr/RenameVars.$(OBJEXT) \ 209 ResolvExpr/ResolveAssertions.$(OBJEXT) \ 210 ResolvExpr/Resolver.$(OBJEXT) \ 209 211 ResolvExpr/ResolveTypeof.$(OBJEXT) \ 212 ResolvExpr/SpecCost.$(OBJEXT) \ 210 213 ResolvExpr/TypeEnvironment.$(OBJEXT) \ 211 214 ResolvExpr/Unify.$(OBJEXT) SymTab/Autogen.$(OBJEXT) \ … … 262 265 ResolvExpr/TypeEnvironment.$(OBJEXT) \ 263 266 ResolvExpr/CurrentObject.$(OBJEXT) \ 264 ResolvExpr/ExplodedActual.$(OBJEXT) SymTab/Indexer.$(OBJEXT) \ 265 SymTab/Mangler.$(OBJEXT) SymTab/ManglerCommon.$(OBJEXT) \ 266 SymTab/Validate.$(OBJEXT) SymTab/FixFunction.$(OBJEXT) \ 267 SymTab/Autogen.$(OBJEXT) SynTree/Type.$(OBJEXT) \ 268 SynTree/VoidType.$(OBJEXT) SynTree/BasicType.$(OBJEXT) \ 269 SynTree/PointerType.$(OBJEXT) SynTree/ArrayType.$(OBJEXT) \ 270 SynTree/ReferenceType.$(OBJEXT) SynTree/FunctionType.$(OBJEXT) \ 267 ResolvExpr/ExplodedActual.$(OBJEXT) \ 268 ResolvExpr/SpecCost.$(OBJEXT) \ 269 ResolvExpr/ResolveAssertions.$(OBJEXT) \ 270 SymTab/Indexer.$(OBJEXT) SymTab/Mangler.$(OBJEXT) \ 271 SymTab/ManglerCommon.$(OBJEXT) SymTab/Validate.$(OBJEXT) \ 272 SymTab/FixFunction.$(OBJEXT) SymTab/Autogen.$(OBJEXT) \ 273 SynTree/Type.$(OBJEXT) SynTree/VoidType.$(OBJEXT) \ 274 SynTree/BasicType.$(OBJEXT) SynTree/PointerType.$(OBJEXT) \ 275 SynTree/ArrayType.$(OBJEXT) SynTree/ReferenceType.$(OBJEXT) \ 276 SynTree/FunctionType.$(OBJEXT) \ 271 277 SynTree/ReferenceToType.$(OBJEXT) SynTree/TupleType.$(OBJEXT) \ 272 278 SynTree/TypeofType.$(OBJEXT) SynTree/AttrType.$(OBJEXT) \ … … 589 595 ResolvExpr/Occurs.cc ResolvExpr/TypeEnvironment.cc \ 590 596 ResolvExpr/CurrentObject.cc ResolvExpr/ExplodedActual.cc \ 597 ResolvExpr/SpecCost.cc ResolvExpr/ResolveAssertions.cc \ 591 598 SymTab/Indexer.cc SymTab/Mangler.cc SymTab/ManglerCommon.cc \ 592 599 SymTab/Validate.cc SymTab/FixFunction.cc SymTab/Autogen.cc \ … … 696 703 ResolvExpr/PtrsCastable.cc \ 697 704 ResolvExpr/RenameVars.cc \ 705 ResolvExpr/ResolveAssertions.cc \ 698 706 ResolvExpr/Resolver.cc \ 699 707 ResolvExpr/ResolveTypeof.cc \ 708 ResolvExpr/SpecCost.cc \ 700 709 ResolvExpr/TypeEnvironment.cc \ 701 710 ResolvExpr/Unify.cc \ … … 946 955 ResolvExpr/RenameVars.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 947 956 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 957 ResolvExpr/ResolveAssertions.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 958 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 948 959 ResolvExpr/Resolver.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 949 960 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 950 961 ResolvExpr/ResolveTypeof.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 962 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 963 ResolvExpr/SpecCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 951 964 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 952 965 ResolvExpr/TypeEnvironment.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ … … 1207 1220 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/PtrsCastable.Po@am__quote@ 1208 1221 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/RenameVars.Po@am__quote@ 1222 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ResolveAssertions.Po@am__quote@ 1209 1223 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ResolveTypeof.Po@am__quote@ 1210 1224 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Resolver.Po@am__quote@ 1225 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/SpecCost.Po@am__quote@ 1211 1226 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/TypeEnvironment.Po@am__quote@ 1212 1227 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Unify.Po@am__quote@ -
src/ResolvExpr/Alternative.cc
r07ec1a2 r276a55b2 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:44:23 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat May 16 23:54:23 201513 // Update Count : 211 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Thu Oct 11 10:55:00 2018 13 // Update Count : 3 14 14 // 15 15 … … 20 20 #include <utility> // for move 21 21 22 #include "Common/utility.h" // for maybeClone22 #include "Common/utility.h" // for cloneAll 23 23 #include "ResolvExpr/Cost.h" // for Cost, Cost::zero, operator<< 24 24 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment … … 27 27 28 28 namespace ResolvExpr { 29 Alternative::Alternative() : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ) {} 29 Alternative::Alternative() 30 : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ), env(), openVars(), need() {} 30 31 31 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost ) 32 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ) {} 32 Alternative::Alternative( Expression *expr, const TypeEnvironment &env ) 33 : cost( Cost::zero ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars(), need() {} 34 35 Alternative::Alternative( const Alternative &o, Expression *expr, const Cost &cost ) 36 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( o.env ), openVars( o.openVars ), 37 need() { cloneAll( o.need, need ); } 33 38 34 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost, const Cost &cvtCost ) 35 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {} 39 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, 40 const OpenVarSet& openVars, const AssertionList& oneed, const Cost& cost ) 41 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars( openVars ), 42 need() { cloneAll( oneed, need ); } 36 43 37 Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) { 38 } 44 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, 45 const OpenVarSet& openVars, const AssertionList& oneed, const Cost& cost, 46 const Cost &cvtCost ) 47 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ), openVars( openVars ), 48 need() { cloneAll( oneed, need ); } 49 50 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, 51 const OpenVarSet &openVars, const AssertionSet &oneed, const Cost &cost) 52 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars( openVars ), 53 need() { cloneAll( oneed, need ); } 54 55 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, 56 const OpenVarSet &openVars, const AssertionSet &oneed, const Cost &cost, 57 const Cost& cvtCost ) 58 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ), openVars( openVars ), 59 need() { cloneAll( oneed, need ); } 60 61 Alternative::Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars, 62 AssertionSet &&needSet, const Cost &cost ) 63 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( std::move(env) ), 64 openVars( std::move(openVars) ), need( needSet.begin(), needSet.end() ) {} 65 66 Alternative::Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars, 67 AssertionSet &&needSet, const Cost &cost, const Cost &cvtCost ) 68 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( std::move(env) ), 69 openVars( std::move(openVars) ), need( needSet.begin(), needSet.end() ) {} 70 71 Alternative::Alternative( const Alternative &other ) 72 : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), 73 env( other.env ), openVars( other.openVars ), need() { cloneAll( other.need, need ); } 39 74 40 75 Alternative &Alternative::operator=( const Alternative &other ) { … … 45 80 expr = maybeClone( other.expr ); 46 81 env = other.env; 82 openVars = other.openVars; 83 need.clear(); 84 cloneAll( other.need, need ); 47 85 return *this; 48 86 } 49 87 50 Alternative::Alternative( Alternative && other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), env( std::move( other.env ) ) { 51 other.expr = nullptr; 52 } 88 Alternative::Alternative( Alternative && other ) 89 : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), 90 env( std::move( other.env ) ), openVars( std::move( other.openVars ) ), 91 need( std::move( other.need ) ) { other.expr = nullptr; } 53 92 54 93 Alternative & Alternative::operator=( Alternative && other ) { … … 59 98 expr = other.expr; 60 99 env = std::move( other.env ); 100 openVars = std::move( other.openVars ); 101 need = std::move( other.need ); 61 102 other.expr = nullptr; 62 103 return *this; … … 64 105 65 106 Alternative::~Alternative() { 107 for ( AssertionItem& n : need ) { delete n.decl; } 66 108 delete expr; 67 109 } -
src/ResolvExpr/Alternative.h
r07ec1a2 r276a55b2 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:45:43 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:36:36 201713 // Update Count : 311 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Thu Oct 11 10:55:00 2018 13 // Update Count : 4 14 14 // 15 15 … … 20 20 21 21 #include "Cost.h" // for Cost 22 #include "TypeEnvironment.h" // for TypeEnvironment 22 #include "TypeEnvironment.h" // for TypeEnvironment, AssertionSetValue 23 24 #include "Common/utility.h" // for maybeClone 23 25 24 26 class Expression; 25 27 26 28 namespace ResolvExpr { 29 /// One assertion to resolve 30 struct AssertionItem { 31 DeclarationWithType* decl; 32 AssertionSetValue info; 33 34 AssertionItem() = default; 35 AssertionItem( DeclarationWithType* decl, const AssertionSetValue& info ) 36 : decl(decl), info(info) {} 37 AssertionItem( const AssertionSet::value_type& e ) : decl(e.first), info(e.second) {} 38 operator AssertionSet::value_type () const { return { decl, info }; } 39 40 // to support cloneAll 41 AssertionItem clone() const { return { maybeClone(decl), info }; } 42 }; 43 /// A list of unresolved assertions 44 using AssertionList = std::vector<AssertionItem>; 45 46 /// Clones an assertion list into an assertion set 47 static inline void cloneAll( const AssertionList& src, AssertionSet& dst ) { 48 for ( const AssertionItem& item : src ) { 49 dst.emplace( maybeClone(item.decl), item.info ); 50 } 51 } 52 53 /// Clones an assertion set into an assertion list 54 static inline void cloneAll( const AssertionSet& src, AssertionList& dst ) { 55 dst.reserve( dst.size() + src.size() ); 56 for ( const auto& entry : src ) { 57 dst.emplace_back( maybeClone(entry.first), entry.second ); 58 } 59 } 60 61 /// Clones an assertion list into an assertion list 62 static inline void cloneAll( const AssertionList& src, AssertionList& dst ) { 63 dst.reserve( dst.size() + src.size() ); 64 for ( const AssertionItem& item : src ) { 65 dst.emplace_back( maybeClone(item.decl), item.info ); 66 } 67 } 68 69 /// One option for resolution of an expression 27 70 struct Alternative { 28 71 Alternative(); 29 Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost ); 30 Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost, const Cost &cvtCost ); 72 Alternative( Expression *expr, const TypeEnvironment &env ); 73 Alternative( const Alternative &o, Expression *expr, const Cost &cost ); 74 Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet& openVars, 75 const AssertionList& need, const Cost &cost ); 76 Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet& openVars, 77 const AssertionList& need, const Cost &cost, const Cost &cvtCost ); 78 Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet &openVars, 79 const AssertionSet &need, const Cost &cost); 80 Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet &openVars, 81 const AssertionSet &need, const Cost &cost, const Cost& cvtCost ); 82 Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars, 83 AssertionSet &&need, const Cost &cost ); 84 Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars, 85 AssertionSet &&need, const Cost &cost, const Cost &cvtCost ); 31 86 Alternative( const Alternative &other ); 32 87 Alternative &operator=( const Alternative &other ); … … 44 99 } 45 100 46 Cost cost; 47 Cost cvtCost; 48 Expression *expr; 49 TypeEnvironment env; 101 /// Sorts by cost 102 bool operator< ( const Alternative& o ) const { return cost < o.cost; } 103 104 Cost cost; ///< Cost of the whole expression 105 Cost cvtCost; ///< Cost of conversions to the satisfying expression 106 Expression *expr; ///< Satisfying expression 107 TypeEnvironment env; ///< Containing type environment 108 OpenVarSet openVars; ///< Open variables for environment 109 AssertionList need; ///< Assertions which need to be resolved 50 110 }; 51 111 -
src/ResolvExpr/AlternativeFinder.cc
r07ec1a2 r276a55b2 11 11 // Last Modified By : Peter A. Buhr 12 12 // Last Modified On : Thu Nov 1 21:00:56 2018 13 // Update Count : 3 413 // Update Count : 35 14 14 // 15 15 … … 34 34 #include "InitTweak/InitTweak.h" // for getFunctionName 35 35 #include "RenameVars.h" // for RenameVars, global_renamer 36 #include "ResolveAssertions.h" // for resolveAssertions 36 37 #include "ResolveTypeof.h" // for resolveTypeof 37 38 #include "Resolver.h" // for resolveStmtExpr … … 102 103 void addAnonConversions( const Alternative & alt ); 103 104 /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member 104 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name );105 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative &alt, const Cost &newCost, const std::string & name ); 105 106 /// Adds alternatives for member expressions where the left side has tuple type 106 void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression *member );107 void addTupleMembers( TupleType *tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member ); 107 108 /// Adds alternatives for offsetof expressions, given the base type and name of the member 108 109 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); … … 113 114 template<typename OutputIterator> 114 115 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out ); 115 /// Checks if assertion parameters match for a newalternative116 /// Sets up parameter inference for an output alternative 116 117 template< typename OutputIterator > 117 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );118 void inferParameters( Alternative &newAlt, OutputIterator out ); 118 119 private: 119 120 AlternativeFinder & altFinder; … … 244 245 } 245 246 246 void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast) {247 void AlternativeFinder::find( Expression *expr, ResolvMode mode ) { 247 248 PassVisitor<Finder> finder( *this ); 248 249 expr->accept( finder ); 249 if ( failFast && alternatives.empty() ) {250 if ( mode.failFast && alternatives.empty() ) { 250 251 PRINT( 251 252 std::cerr << "No reasonable alternatives for expression " << expr << std::endl; … … 253 254 SemanticError( expr, "No reasonable alternatives for expression " ); 254 255 } 255 if ( prune ) { 256 if ( mode.resolveAssns || mode.prune ) { 257 // trim candidates just to those where the assertions resolve 258 // - necessary pre-requisite to pruning 259 AltList candidates; 260 for ( unsigned i = 0; i < alternatives.size(); ++i ) { 261 resolveAssertions( alternatives[i], indexer, candidates ); 262 } 263 // fail early if none such 264 if ( mode.failFast && candidates.empty() ) { 265 std::ostringstream stream; 266 stream << "No resolvable alternatives for expression " << expr << "\n" 267 << "Alternatives with failing assertions are:\n"; 268 printAlts( alternatives, stream, 1 ); 269 SemanticError( expr->location, stream.str() ); 270 } 271 // reset alternatives 272 alternatives = std::move( candidates ); 273 } 274 if ( mode.prune ) { 256 275 auto oldsize = alternatives.size(); 257 276 PRINT( … … 261 280 AltList pruned; 262 281 pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) ); 263 if ( failFast && pruned.empty() ) {282 if ( mode.failFast && pruned.empty() ) { 264 283 std::ostringstream stream; 265 284 AltList winners; … … 280 299 } 281 300 // adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted 282 for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i) {283 if ( adjust) {284 adjustExprType( i ->expr->get_result(), i->env, indexer );301 if ( mode.adjust ) { 302 for ( Alternative& i : alternatives ) { 303 adjustExprType( i.expr->get_result(), i.env, indexer ); 285 304 } 286 305 } … … 294 313 295 314 void AlternativeFinder::findWithAdjustment( Expression *expr ) { 296 find( expr, true);315 find( expr, ResolvMode::withAdjustment() ); 297 316 } 298 317 299 318 void AlternativeFinder::findWithoutPrune( Expression * expr ) { 300 find( expr, true, false);319 find( expr, ResolvMode::withoutPrune() ); 301 320 } 302 321 303 322 void AlternativeFinder::maybeFind( Expression * expr ) { 304 find( expr, true, true, false);323 find( expr, ResolvMode::withoutFailFast() ); 305 324 } 306 325 … … 317 336 318 337 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) { 319 addAggMembers( structInst, aggrExpr.get(), alt .cost+Cost::safe, alt.env, "" );338 addAggMembers( structInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" ); 320 339 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) { 321 addAggMembers( unionInst, aggrExpr.get(), alt .cost+Cost::safe, alt.env, "" );340 addAggMembers( unionInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" ); 322 341 } // if 323 342 } 324 343 325 344 template< typename StructOrUnionType > 326 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) {345 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative& alt, const Cost &newCost, const std::string & name ) { 327 346 std::list< Declaration* > members; 328 347 aggInst->lookup( name, members ); … … 332 351 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 333 352 // can't construct in place and use vector::back 334 Alternative newAlt ( new MemberExpr( dwt, expr->clone() ), env, newCost );353 Alternative newAlt{ alt, new MemberExpr{ dwt, expr->clone() }, newCost }; 335 354 renameTypes( newAlt.expr ); 336 355 addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression. … … 342 361 } 343 362 344 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression *member ) {363 void AlternativeFinder::Finder::addTupleMembers( TupleType *tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member ) { 345 364 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) { 346 365 // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning … … 348 367 std::string tmp; 349 368 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 350 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) ); 369 alternatives.push_back( Alternative{ 370 alt, new TupleIndexExpr( expr->clone(), val ), newCost } ); 351 371 } // if 352 372 } // if … … 354 374 355 375 void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) { 356 alternatives.push_back( Alternative ( applicationExpr->clone(), env, Cost::zero ));376 alternatives.push_back( Alternative{ applicationExpr->clone(), env } ); 357 377 } 358 378 … … 410 430 Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) { 411 431 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( alt.expr ); 412 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr-> get_function()->get_result());413 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer-> get_base());432 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result ); 433 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base ); 414 434 415 435 Cost convCost = Cost::zero; 416 std::list< DeclarationWithType* >& formals = function-> get_parameters();436 std::list< DeclarationWithType* >& formals = function->parameters; 417 437 std::list< DeclarationWithType* >::iterator formal = formals.begin(); 418 std::list< Expression* >& actuals = appExpr-> get_args();419 420 for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr) {421 Type * actualType = (*actualExpr)->get_result();438 std::list< Expression* >& actuals = appExpr->args; 439 440 for ( Expression*& actualExpr : actuals ) { 441 Type * actualType = actualExpr->result; 422 442 PRINT( 423 443 std::cerr << "actual expression:" << std::endl; 424 (*actualExpr)->print( std::cerr, 8 );444 actualExpr->print( std::cerr, 8 ); 425 445 std::cerr << "--- results are" << std::endl; 426 446 actualType->print( std::cerr, 8 ); 427 447 ) 428 448 if ( formal == formals.end() ) { 429 if ( function-> get_isVarArgs()) {449 if ( function->isVarArgs ) { 430 450 convCost.incUnsafe(); 431 451 PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; ) 432 452 // convert reference-typed expressions to value-typed expressions 433 referenceToRvalueConversion( *actualExpr, convCost );453 referenceToRvalueConversion( actualExpr, convCost ); 434 454 continue; 435 455 } else { … … 437 457 } 438 458 } 439 if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) {459 if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( actualExpr ) ) { 440 460 // default arguments should be free - don't include conversion cost. 441 461 // Unwrap them here because they are not relevant to the rest of the system. 442 *actualExpr = def->expr;462 actualExpr = def->expr; 443 463 ++formal; 444 464 continue; 445 465 } 466 // mark conversion cost to formal and also specialization cost of formal type 446 467 Type * formalType = (*formal)->get_type(); 447 convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env ); 468 convCost += computeExpressionConversionCost( actualExpr, formalType, indexer, alt.env ); 469 convCost.decSpec( specCost( formalType ) ); 448 470 ++formal; // can't be in for-loop update because of the continue 449 471 } … … 452 474 } 453 475 454 for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) { 476 // mark specialization cost of return types 477 for ( DeclarationWithType* returnVal : function->returnVals ) { 478 convCost.decSpec( specCost( returnVal->get_type() ) ); 479 } 480 481 // mark type variable and specialization cost of forall clause 482 convCost.incVar( function->forall.size() ); 483 for ( TypeDecl* td : function->forall ) { 484 convCost.decSpec( td->assertions.size() ); 485 } 486 487 // xxx -- replace with new costs in resolver 488 for ( InferredParams::const_iterator assert = appExpr->inferParams.begin(); assert != appExpr->inferParams.end(); ++assert ) { 455 489 convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env ); 456 490 } … … 466 500 needAssertions[ *assert ].isUsed = true; 467 501 } 468 /// needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() ); 469 } 470 } 471 472 static const int recursionLimit = /*10*/ 4; ///< Limit to depth of recursion satisfaction 473 474 void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) { 475 for ( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i ) { 476 if ( i->second.isUsed ) { 477 indexer.addId( i->first ); 478 } 479 } 480 } 481 482 template< typename ForwardIterator, typename OutputIterator > 483 void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, int level, const SymTab::Indexer &indexer, OutputIterator out ) { 484 if ( newAlt.cost == Cost::infinity ) return; // don't proceed down this dead end 485 if ( begin == end ) { 486 if ( newNeed.empty() ) { 487 PRINT( 488 std::cerr << "all assertions satisfied, output alternative: "; 489 newAlt.print( std::cerr ); 490 std::cerr << std::endl; 491 ); 492 *out++ = newAlt; 493 return; 494 } else if ( level >= recursionLimit ) { 495 SemanticError( newAlt.expr->location, "Too many recursive assertions" ); 496 } else { 497 AssertionSet newerNeed; 498 PRINT( 499 std::cerr << "recursing with new set:" << std::endl; 500 printAssertionSet( newNeed, std::cerr, 8 ); 501 ) 502 inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out ); 503 return; 504 } 505 } 506 507 ForwardIterator cur = begin++; 508 if ( ! cur->second.isUsed ) { 509 inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out ); 510 return; // xxx - should this continue? previously this wasn't here, and it looks like it should be 511 } 512 DeclarationWithType *curDecl = cur->first; 513 514 PRINT( 515 std::cerr << "inferRecursive: assertion is "; 516 curDecl->print( std::cerr ); 517 std::cerr << std::endl; 518 ) 519 std::list< SymTab::Indexer::IdData > candidates; 520 decls.lookupId( curDecl->get_name(), candidates ); 521 /// if ( candidates.empty() ) { std::cerr << "no candidates!" << std::endl; } 522 for ( const auto & data : candidates ) { 523 DeclarationWithType * candidate = data.id; 524 PRINT( 525 std::cerr << "inferRecursive: candidate is "; 526 candidate->print( std::cerr ); 527 std::cerr << std::endl; 528 ) 529 530 AssertionSet newHave, newerNeed( newNeed ); 531 TypeEnvironment newEnv( newAlt.env ); 532 OpenVarSet newOpenVars( openVars ); 533 Type *adjType = candidate->get_type()->clone(); 534 adjustExprType( adjType, newEnv, indexer ); 535 renameTyVars( adjType ); 536 PRINT( 537 std::cerr << "unifying "; 538 curDecl->get_type()->print( std::cerr ); 539 std::cerr << " with "; 540 adjType->print( std::cerr ); 541 std::cerr << std::endl; 542 ) 543 if ( unify( curDecl->get_type(), adjType, newEnv, newerNeed, newHave, newOpenVars, indexer ) ) { 544 PRINT( 545 std::cerr << "success!" << std::endl; 546 ) 547 SymTab::Indexer newDecls( decls ); 548 addToIndexer( newHave, newDecls ); 549 Alternative newerAlt( newAlt ); 550 newerAlt.env = newEnv; 551 assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() ); 552 553 // everything with an empty idChain was pulled in by the current assertion. 554 // add current assertion's idChain + current assertion's ID so that the correct inferParameters can be found. 555 for ( auto & a : newerNeed ) { 556 if ( a.second.idChain.empty() ) { 557 a.second.idChain = cur->second.idChain; 558 a.second.idChain.push_back( curDecl->get_uniqueId() ); 559 } 560 } 561 562 Expression *varExpr = data.combine( newerAlt.cvtCost ); 563 delete varExpr->get_result(); 564 varExpr->set_result( adjType->clone() ); 565 PRINT( 566 std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " "; 567 curDecl->print( std::cerr ); 568 std::cerr << " with declaration " << candidate->get_uniqueId() << " "; 569 candidate->print( std::cerr ); 570 std::cerr << std::endl; 571 ) 572 // follow the current assertion's ID chain to find the correct set of inferred parameters to add the candidate to (i.e. the set of inferred parameters belonging to the entity which requested the assertion parameter). 573 InferredParams * inferParameters = &newerAlt.expr->get_inferParams(); 574 for ( UniqueId id : cur->second.idChain ) { 575 inferParameters = (*inferParameters)[ id ].inferParams.get(); 576 } 577 // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions 578 (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr ); 579 inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out ); 580 } else { 581 delete adjType; 582 } 583 } 584 } 502 } 503 } 504 505 /// Unique identifier for matching expression resolutions to their requesting expression 506 UniqueId globalResnSlot = 0; 585 507 586 508 template< typename OutputIterator > 587 void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) { 588 // PRINT( 589 // std::cerr << "inferParameters: assertions needed are" << std::endl; 590 // printAll( need, std::cerr, 8 ); 591 // ) 592 SymTab::Indexer decls( indexer ); 593 // PRINT( 594 // std::cerr << "============= original indexer" << std::endl; 595 // indexer.print( std::cerr ); 596 // std::cerr << "============= new indexer" << std::endl; 597 // decls.print( std::cerr ); 598 // ) 599 addToIndexer( have, decls ); 600 AssertionSet newNeed; 601 PRINT( 602 std::cerr << "env is: " << std::endl; 603 newAlt.env.print( std::cerr, 0 ); 604 std::cerr << std::endl; 605 ) 606 607 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out ); 608 // PRINT( 609 // std::cerr << "declaration 14 is "; 610 // Declaration::declFromId 611 // *out++ = newAlt; 612 // ) 509 void AlternativeFinder::Finder::inferParameters( Alternative &newAlt, OutputIterator out ) { 510 // Set need bindings for any unbound assertions 511 UniqueId crntResnSlot = 0; // matching ID for this expression's assertions 512 for ( auto& assn : newAlt.need ) { 513 // skip already-matched assertions 514 if ( assn.info.resnSlot != 0 ) continue; 515 // assign slot for expression if needed 516 if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; } 517 // fix slot to assertion 518 assn.info.resnSlot = crntResnSlot; 519 } 520 // pair slot to expression 521 if ( crntResnSlot != 0 ) { newAlt.expr->resnSlots.push_back( crntResnSlot ); } 522 523 // add to output list, assertion resolution is deferred 524 *out++ = newAlt; 613 525 } 614 526 … … 951 863 } 952 864 // build and validate new alternative 953 Alternative newAlt ( appExpr, result.env, cost );865 Alternative newAlt{ appExpr, result.env, result.openVars, result.need, cost }; 954 866 PRINT( 955 867 std::cerr << "instantiate function success: " << appExpr << std::endl; … … 957 869 printAssertionSet( result.need, std::cerr, 8 ); 958 870 ) 959 inferParameters( result.need, result.have, newAlt, result.openVars, out );871 inferParameters( newAlt, out ); 960 872 } 961 873 … … 1202 1114 1203 1115 // function may return struct or union value, in which case we need to add alternatives 1204 // for implicit conversions to each of the anonymous members, must happen after findMinCost1116 // for implicit conversions to each of the anonymous members, must happen after findMinCost 1205 1117 // since anon conversions are never the cheapest expression 1206 1118 for ( const Alternative & alt : winners ) { … … 1234 1146 if ( isLvalue( alt.expr ) ) { 1235 1147 alternatives.push_back( 1236 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } );1148 Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } ); 1237 1149 } // if 1238 1150 } // for … … 1240 1152 1241 1153 void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) { 1242 alternatives.push_back( Alternative{ expr->clone(), env , Cost::zero} );1154 alternatives.push_back( Alternative{ expr->clone(), env } ); 1243 1155 } 1244 1156 … … 1285 1197 AltList candidates; 1286 1198 for ( Alternative & alt : finder.alternatives ) { 1287 AssertionSet needAssertions, haveAssertions; 1288 OpenVarSet openVars; 1199 AssertionSet needAssertions( alt.need.begin(), alt.need.end() ); 1200 AssertionSet haveAssertions; 1201 OpenVarSet openVars{ alt.openVars }; 1289 1202 1290 1203 alt.env.extractOpenVars( openVars ); … … 1314 1227 // count one safe conversion for each value that is thrown away 1315 1228 thisCost.incSafe( discardedValues ); 1316 Alternative newAlt ( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env,1317 alt.cost, thisCost );1318 inferParameters( needAssertions, haveAssertions, newAlt, openVars,1319 1229 Alternative newAlt{ 1230 restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), 1231 alt.env, openVars, needAssertions, alt.cost + thisCost, thisCost }; 1232 inferParameters( newAlt, back_inserter( candidates ) ); 1320 1233 } // if 1321 1234 } // for … … 1330 1243 1331 1244 void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) { 1332 assertf( castExpr->get_result(), "Implic atevirtual cast targets not yet supported." );1245 assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." ); 1333 1246 AlternativeFinder finder( indexer, env ); 1334 1247 // don't prune here, since it's guaranteed all alternatives will have the same type 1335 1248 finder.findWithoutPrune( castExpr->get_arg() ); 1336 1249 for ( Alternative & alt : finder.alternatives ) { 1337 alternatives.push_back( Alternative (1338 new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ),1339 alt. env, alt.cost ));1250 alternatives.push_back( Alternative{ 1251 alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() }, 1252 alt.cost } ); 1340 1253 } 1341 1254 } … … 1365 1278 // find member of the given type 1366 1279 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 1367 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );1280 addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) ); 1368 1281 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 1369 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );1282 addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) ); 1370 1283 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 1371 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );1284 addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() ); 1372 1285 } // if 1373 1286 } // for … … 1375 1288 1376 1289 void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) { 1377 alternatives.push_back( Alternative ( memberExpr->clone(), env, Cost::zero ));1290 alternatives.push_back( Alternative{ memberExpr->clone(), env } ); 1378 1291 } 1379 1292 … … 1388 1301 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 1389 1302 // can't construct in place and use vector::back 1390 Alternative newAlt ( newExpr, env, Cost::zero, cost );1303 Alternative newAlt{ newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost }; 1391 1304 PRINT( 1392 1305 std::cerr << "decl is "; … … 1406 1319 // not sufficient to clone here, because variable's type may have changed 1407 1320 // since the VariableExpr was originally created. 1408 alternatives.push_back( Alternative ( new VariableExpr( variableExpr->var ), env, Cost::zero ));1321 alternatives.push_back( Alternative{ new VariableExpr{ variableExpr->var }, env } ); 1409 1322 } 1410 1323 1411 1324 void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) { 1412 alternatives.push_back( Alternative ( constantExpr->clone(), env, Cost::zero ));1325 alternatives.push_back( Alternative{ constantExpr->clone(), env } ); 1413 1326 } 1414 1327 … … 1416 1329 if ( sizeofExpr->get_isType() ) { 1417 1330 Type * newType = sizeofExpr->get_type()->clone(); 1418 alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1331 alternatives.push_back( Alternative{ 1332 new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1419 1333 } else { 1420 1334 // find all alternatives for the argument to sizeof … … 1430 1344 Alternative &choice = winners.front(); 1431 1345 referenceToRvalueConversion( choice.expr, choice.cost ); 1432 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1346 alternatives.push_back( Alternative{ 1347 choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } ); 1433 1348 } // if 1434 1349 } … … 1437 1352 if ( alignofExpr->get_isType() ) { 1438 1353 Type * newType = alignofExpr->get_type()->clone(); 1439 alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1354 alternatives.push_back( Alternative{ 1355 new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1440 1356 } else { 1441 1357 // find all alternatives for the argument to sizeof … … 1451 1367 Alternative &choice = winners.front(); 1452 1368 referenceToRvalueConversion( choice.expr, choice.cost ); 1453 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1369 alternatives.push_back( Alternative{ 1370 choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } ); 1454 1371 } // if 1455 1372 } … … 1461 1378 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) { 1462 1379 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) { 1463 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) ); 1380 alternatives.push_back( Alternative{ 1381 new OffsetofExpr{ aggInst->clone(), dwt }, env } ); 1464 1382 renameTypes( alternatives.back().expr ); 1465 1383 } else { … … 1480 1398 1481 1399 void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) { 1482 alternatives.push_back( Alternative ( offsetofExpr->clone(), env, Cost::zero ));1400 alternatives.push_back( Alternative{ offsetofExpr->clone(), env } ); 1483 1401 } 1484 1402 1485 1403 void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) { 1486 alternatives.push_back( Alternative ( offsetPackExpr->clone(), env, Cost::zero ));1404 alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } ); 1487 1405 } 1488 1406 … … 1504 1422 Cost cost = Cost::zero; 1505 1423 Expression * newExpr = data.combine( cost ); 1506 alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) ); 1424 alternatives.push_back( Alternative{ 1425 new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{}, 1426 AssertionList{}, Cost::zero, cost } ); 1507 1427 for ( DeclarationWithType * retVal : function->returnVals ) { 1508 1428 alternatives.back().expr->result = retVal->get_type()->clone(); … … 1543 1463 Cost cost = Cost::zero; 1544 1464 Expression * newExpr = data.combine( cost ); 1545 alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) ); 1465 alternatives.push_back( Alternative{ 1466 newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost } ); 1546 1467 renameTypes( alternatives.back().expr ); 1547 1468 } // for … … 1558 1479 for ( const Alternative & first : firstFinder.alternatives ) { 1559 1480 for ( const Alternative & second : secondFinder.alternatives ) { 1560 TypeEnvironment compositeEnv; 1561 compositeEnv.simpleCombine( first.env ); 1481 TypeEnvironment compositeEnv{ first.env }; 1562 1482 compositeEnv.simpleCombine( second.env ); 1563 1564 LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() ); 1565 alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) ); 1483 OpenVarSet openVars{ first.openVars }; 1484 mergeOpenVars( openVars, second.openVars ); 1485 AssertionSet need; 1486 cloneAll( first.need, need ); 1487 cloneAll( second.need, need ); 1488 1489 LogicalExpr *newExpr = new LogicalExpr{ 1490 first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() }; 1491 alternatives.push_back( Alternative{ 1492 newExpr, std::move(compositeEnv), std::move(openVars), 1493 AssertionList( need.begin(), need.end() ), first.cost + second.cost } ); 1566 1494 } 1567 1495 } … … 1584 1512 for ( const Alternative & second : secondFinder.alternatives ) { 1585 1513 for ( const Alternative & third : thirdFinder.alternatives ) { 1586 TypeEnvironment compositeEnv; 1587 compositeEnv.simpleCombine( first.env ); 1514 TypeEnvironment compositeEnv{ first.env }; 1588 1515 compositeEnv.simpleCombine( second.env ); 1589 1516 compositeEnv.simpleCombine( third.env ); 1590 1517 OpenVarSet openVars{ first.openVars }; 1518 mergeOpenVars( openVars, second.openVars ); 1519 mergeOpenVars( openVars, third.openVars ); 1520 AssertionSet need; 1521 cloneAll( first.need, need ); 1522 cloneAll( second.need, need ); 1523 cloneAll( third.need, need ); 1524 AssertionSet have; 1525 1591 1526 // unify true and false types, then infer parameters to produce new alternatives 1592 OpenVarSet openVars;1593 AssertionSet needAssertions, haveAssertions;1594 Alternative newAlt( 0, compositeEnv, first.cost + second.cost + third.cost );1595 1527 Type* commonType = nullptr; 1596 if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1597 ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() ); 1528 if ( unify( second.expr->result, third.expr->result, compositeEnv, 1529 need, have, openVars, indexer, commonType ) ) { 1530 ConditionalExpr *newExpr = new ConditionalExpr{ 1531 first.expr->clone(), second.expr->clone(), third.expr->clone() }; 1598 1532 newExpr->result = commonType ? commonType : second.expr->result->clone(); 1599 1533 // convert both options to the conditional result type 1600 newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env ); 1601 newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env ); 1602 newAlt.expr = newExpr; 1603 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 1534 Cost cost = first.cost + second.cost + third.cost; 1535 cost += computeExpressionConversionCost( 1536 newExpr->arg2, newExpr->result, indexer, compositeEnv ); 1537 cost += computeExpressionConversionCost( 1538 newExpr->arg3, newExpr->result, indexer, compositeEnv ); 1539 // output alternative 1540 Alternative newAlt{ 1541 newExpr, std::move(compositeEnv), std::move(openVars), 1542 AssertionList( need.begin(), need.end() ), cost }; 1543 inferParameters( newAlt, back_inserter( alternatives ) ); 1604 1544 } // if 1605 1545 } // for … … 1614 1554 secondFinder.findWithAdjustment( commaExpr->get_arg2() ); 1615 1555 for ( const Alternative & alt : secondFinder.alternatives ) { 1616 alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) ); 1556 alternatives.push_back( Alternative{ 1557 alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } ); 1617 1558 } // for 1618 1559 delete newFirstArg; … … 1629 1570 for ( const Alternative & first : firstFinder.alternatives ) { 1630 1571 for ( const Alternative & second : secondFinder.alternatives ) { 1631 TypeEnvironment compositeEnv; 1632 compositeEnv.simpleCombine( first.env ); 1572 TypeEnvironment compositeEnv{ first.env }; 1633 1573 compositeEnv.simpleCombine( second.env ); 1634 OpenVarSet openVars; 1635 AssertionSet needAssertions, haveAssertions; 1636 Alternative newAlt( 0, compositeEnv, first.cost + second.cost ); 1574 OpenVarSet openVars{ first.openVars }; 1575 mergeOpenVars( openVars, second.openVars ); 1576 AssertionSet need; 1577 cloneAll( first.need, need ); 1578 cloneAll( second.need, need ); 1579 AssertionSet have; 1580 1637 1581 Type* commonType = nullptr; 1638 if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) { 1639 RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() ); 1582 if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have, 1583 openVars, indexer, commonType ) ) { 1584 RangeExpr * newExpr = 1585 new RangeExpr{ first.expr->clone(), second.expr->clone() }; 1640 1586 newExpr->result = commonType ? commonType : first.expr->result->clone(); 1641 newAlt.expr = newExpr; 1642 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 1587 Alternative newAlt{ 1588 newExpr, std::move(compositeEnv), std::move(openVars), 1589 AssertionList( need.begin(), need.end() ), first.cost + second.cost }; 1590 inferParameters( newAlt, back_inserter( alternatives ) ); 1643 1591 } // if 1644 1592 } // for … … 1658 1606 1659 1607 TypeEnvironment compositeEnv; 1660 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1661 alternatives.push_back( 1662 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 1608 OpenVarSet openVars; 1609 AssertionSet need; 1610 for ( const Alternative& alt : alts ) { 1611 compositeEnv.simpleCombine( alt.env ); 1612 mergeOpenVars( openVars, alt.openVars ); 1613 cloneAll( alt.need, need ); 1614 } 1615 1616 alternatives.push_back( Alternative{ 1617 new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars), 1618 AssertionList( need.begin(), need.end() ), sumCost( alts ) } ); 1663 1619 } // for 1664 1620 } 1665 1621 1666 1622 void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) { 1667 alternatives.push_back( Alternative ( tupleExpr->clone(), env, Cost::zero ));1623 alternatives.push_back( Alternative{ tupleExpr->clone(), env } ); 1668 1624 } 1669 1625 1670 1626 void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) { 1671 alternatives.push_back( Alternative ( impCpCtorExpr->clone(), env, Cost::zero ));1627 alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } ); 1672 1628 } 1673 1629 … … 1678 1634 finder.findWithoutPrune( ctorExpr->get_callExpr() ); 1679 1635 for ( Alternative & alt : finder.alternatives ) { 1680 alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) ); 1636 alternatives.push_back( Alternative{ 1637 alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } ); 1681 1638 } 1682 1639 } 1683 1640 1684 1641 void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) { 1685 alternatives.push_back( Alternative ( tupleExpr->clone(), env, Cost::zero ));1642 alternatives.push_back( Alternative{ tupleExpr->clone(), env } ); 1686 1643 } 1687 1644 1688 1645 void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) { 1689 alternatives.push_back( Alternative ( tupleAssignExpr->clone(), env, Cost::zero ));1646 alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } ); 1690 1647 } 1691 1648 … … 1696 1653 // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked" 1697 1654 UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() ); 1698 alternatives.push_back( Alternative ( newUnqExpr, alt.env, alt.cost ));1655 alternatives.push_back( Alternative{ alt, newUnqExpr, alt.cost } ); 1699 1656 } 1700 1657 } … … 1704 1661 ResolvExpr::resolveStmtExpr( newStmtExpr, indexer ); 1705 1662 // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr... 1706 alternatives.push_back( Alternative ( newStmtExpr, env, Cost::zero ));1663 alternatives.push_back( Alternative{ newStmtExpr, env } ); 1707 1664 } 1708 1665 … … 1726 1683 for ( Alternative & alt : finder.get_alternatives() ) { 1727 1684 TypeEnvironment newEnv( alt.env ); 1728 AssertionSet needAssertions, haveAssertions; 1729 OpenVarSet openVars; // find things in env that don't have a "representative type" and claim those are open vars? 1685 AssertionSet need; 1686 cloneAll( alt.need, need ); 1687 AssertionSet have; 1688 OpenVarSet openVars( alt.openVars ); 1689 // xxx - find things in env that don't have a "representative type" and claim 1690 // those are open vars? 1730 1691 PRINT( 1731 1692 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1732 1693 ) 1733 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1734 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results 1735 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1736 // to. 1694 // It's possible that a cast can throw away some values in a multiply-valued 1695 // expression. (An example is a cast-to-void, which casts from one value to 1696 // zero.) Figure out the prefix of the subexpression results that are cast 1697 // directly. The candidate is invalid if it has fewer results than there are 1698 // types to cast to. 1737 1699 int discardedValues = alt.expr->result->size() - toType->size(); 1738 1700 if ( discardedValues < 0 ) continue; 1739 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1740 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1701 // xxx - may need to go into tuple types and extract relevant types and use 1702 // unifyList. Note that currently, this does not allow casting a tuple to an 1703 // atomic type (e.g. (int)([1, 2, 3])) 1704 1741 1705 // unification run for side-effects 1742 unify( toType, alt.expr->result, newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?? 1706 unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer ); 1707 // xxx - do some inspecting on this line... why isn't result bound to initAlt.type? 1743 1708 1744 1709 Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv ); … … 1746 1711 // count one safe conversion for each value that is thrown away 1747 1712 thisCost.incSafe( discardedValues ); 1748 Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ); 1749 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 1713 Alternative newAlt{ 1714 new InitExpr{ 1715 restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() }, 1716 std::move(newEnv), std::move(openVars), 1717 AssertionList( need.begin(), need.end() ), alt.cost, thisCost }; 1718 inferParameters( newAlt, back_inserter( candidates ) ); 1750 1719 } 1751 1720 } -
src/ResolvExpr/AlternativeFinder.h
r07ec1a2 r276a55b2 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:56:12 2015 11 // Last Modified By : A ndrew Beach12 // Last Modified On : Wed Jul 26 11:24:00 201713 // Update Count : 411 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Fri Oct -5 10:01:00 2018 13 // Update Count : 5 14 14 // 15 15 … … 24 24 #include "ResolvExpr/Cost.h" // for Cost, Cost::infinity 25 25 #include "ResolvExpr/TypeEnvironment.h" // for AssertionSet, OpenVarSet 26 #include "ResolvMode.h" // for ResolvMode 26 27 #include "SynTree/Visitor.h" // for Visitor 27 28 #include "SynTree/SynTree.h" // for Visitor Nodes … … 68 69 } 69 70 70 void find( Expression *expr, bool adjust = false, bool prune = true, bool failFast = true);71 void find( Expression *expr, ResolvMode mode = ResolvMode{} ); 71 72 /// Calls find with the adjust flag set; adjustment turns array and function types into equivalent pointer types 72 73 void findWithAdjustment( Expression *expr ); -
src/ResolvExpr/ConversionCost.cc
r07ec1a2 r276a55b2 28 28 29 29 namespace ResolvExpr { 30 const Cost Cost::zero = Cost( 0, 0, 0, 0 ); 31 const Cost Cost::infinity = Cost( -1, -1, -1, -1 ); 32 const Cost Cost::unsafe = Cost( 1, 0, 0, 0 ); 33 const Cost Cost::poly = Cost( 0, 1, 0, 0 ); 34 const Cost Cost::safe = Cost( 0, 0, 1, 0 ); 35 const Cost Cost::reference = Cost( 0, 0, 0, 1 ); 30 const Cost Cost::zero = Cost{ 0, 0, 0, 0, 0, 0 }; 31 const Cost Cost::infinity = Cost{ -1, -1, -1, -1, 1, -1 }; 32 const Cost Cost::unsafe = Cost{ 1, 0, 0, 0, 0, 0 }; 33 const Cost Cost::poly = Cost{ 0, 1, 0, 0, 0, 0 }; 34 const Cost Cost::safe = Cost{ 0, 0, 1, 0, 0, 0 }; 35 const Cost Cost::var = Cost{ 0, 0, 0, 1, 0, 0 }; 36 const Cost Cost::spec = Cost{ 0, 0, 0, 0, -1, 0 }; 37 const Cost Cost::reference = Cost{ 0, 0, 0, 0, 0, 1 }; 36 38 37 39 #if 0 -
src/ResolvExpr/Cost.h
r07ec1a2 r276a55b2 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 09:39:50 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:35:55 201713 // Update Count : 511 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Fri Oct 05 14:32:00 2018 13 // Update Count : 7 14 14 // 15 15 … … 21 21 class Cost { 22 22 private: 23 Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ); 23 Cost( int unsafeCost, int polyCost, int safeCost, int varCost, int specCost, 24 int referenceCost ); 24 25 25 26 public: … … 27 28 Cost & incPoly( int inc = 1 ); 28 29 Cost & incSafe( int inc = 1 ); 30 Cost & incVar( int inc = 1 ); 31 Cost & decSpec( int inc = 1 ); 29 32 Cost & incReference( int inc = 1 ); 30 33 … … 32 35 int get_polyCost() const { return polyCost; } 33 36 int get_safeCost() const { return safeCost; } 37 int get_varCost() const { return varCost; } 38 int get_specCost() const { return specCost; } 34 39 int get_referenceCost() const { return referenceCost; } 35 40 … … 41 46 bool operator!=( const Cost &other ) const; 42 47 friend std::ostream &operator<<( std::ostream &os, const Cost &cost ); 48 // returns negative for *this < other, 0 for *this == other, positive for *this > other 49 int compare( const Cost &other ) const; 43 50 44 51 static const Cost zero; … … 48 55 static const Cost poly; 49 56 static const Cost safe; 57 static const Cost var; 58 static const Cost spec; 50 59 static const Cost reference; 60 51 61 private: 52 int compare( const Cost &other ) const;53 54 int unsafeCost;55 int polyCost;56 int s afeCost;57 int referenceCost; 62 int unsafeCost; ///< Unsafe (narrowing) conversions 63 int polyCost; ///< Count of parameters and return values bound to some poly type 64 int safeCost; ///< Safe (widening) conversions 65 int varCost; ///< Count of polymorphic type variables 66 int specCost; ///< Polymorphic type specializations (type assertions), negative cost 67 int referenceCost; ///< reference conversions 58 68 }; 59 69 60 inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ) : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), referenceCost( referenceCost ) {} 70 inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int varCost, int specCost, 71 int referenceCost ) 72 : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), varCost( varCost ), 73 specCost( specCost ), referenceCost( referenceCost ) {} 61 74 62 75 inline Cost & Cost::incUnsafe( int inc ) { … … 75 88 if ( *this == infinity ) return *this; 76 89 safeCost += inc; 90 return *this; 91 } 92 93 inline Cost & Cost::incVar( int inc ) { 94 if ( *this == infinity ) return *this; 95 varCost += inc; 96 return *this; 97 } 98 99 inline Cost& Cost::decSpec( int dec ) { 100 if ( *this == infinity ) return *this; 101 specCost -= dec; 77 102 return *this; 78 103 } … … 86 111 inline Cost Cost::operator+( const Cost &other ) const { 87 112 if ( *this == infinity || other == infinity ) return infinity; 88 return Cost( unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost, referenceCost + other.referenceCost ); 113 return Cost{ 114 unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost, 115 varCost + other.varCost, specCost + other.specCost, 116 referenceCost + other.referenceCost }; 89 117 } 90 118 91 119 inline Cost Cost::operator-( const Cost &other ) const { 92 120 if ( *this == infinity || other == infinity ) return infinity; 93 return Cost( unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost, referenceCost - other.referenceCost ); 121 return Cost{ 122 unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost, 123 varCost - other.varCost, specCost - other.specCost, 124 referenceCost - other.referenceCost }; 94 125 } 95 126 … … 103 134 polyCost += other.polyCost; 104 135 safeCost += other.safeCost; 136 varCost += other.varCost; 137 specCost += other.specCost; 105 138 referenceCost += other.referenceCost; 106 139 return *this; … … 123 156 } else if ( safeCost < other.safeCost ) { 124 157 return true; 158 } else if ( varCost > other.varCost ) { 159 return false; 160 } else if ( varCost < other.varCost ) { 161 return true; 162 } else if ( specCost > other.specCost ) { 163 return false; 164 } else if ( specCost > other.specCost ) { 165 return true; 125 166 } else if ( referenceCost > other.referenceCost ) { 126 167 return false; … … 130 171 return false; 131 172 } // if 173 } 174 175 inline int Cost::compare( const Cost &other ) const { 176 if ( *this == infinity ) return +1; 177 if ( other == infinity ) return -1; 178 179 int c = unsafeCost - other.unsafeCost; if ( c ) return c; 180 c = polyCost - other.polyCost; if ( c ) return c; 181 c = safeCost - other.safeCost; if ( c ) return c; 182 c = varCost - other.varCost; if ( c ) return c; 183 c = specCost - other.specCost; if ( c ) return c; 184 return referenceCost - other.referenceCost; 132 185 } 133 186 … … 136 189 && polyCost == other.polyCost 137 190 && safeCost == other.safeCost 191 && varCost == other.varCost 192 && specCost == other.specCost 138 193 && referenceCost == other.referenceCost; 139 194 } … … 144 199 145 200 inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) { 146 os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " << cost.safeCost << ", " << cost.referenceCost << " )"; 147 return os; 201 return os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " 202 << cost.safeCost << ", " << cost.varCost << ", " << cost.specCost << ", " 203 << cost.referenceCost << " )"; 148 204 } 149 205 } // namespace ResolvExpr -
src/ResolvExpr/Resolver.cc
r07ec1a2 r276a55b2 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:17:01 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Feb 17 11:19:40 201813 // Update Count : 21 311 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Fri Oct 05 09:43:00 2018 13 // Update Count : 214 14 14 // 15 15 16 #include <stddef.h> // for NULL17 16 #include <cassert> // for strict_dynamic_cast, assert 18 17 #include <memory> // for allocator, allocator_traits<... 19 18 #include <tuple> // for get 20 #include <vector> 19 #include <vector> // for vector 21 20 22 21 #include "Alternative.h" // for Alternative, AltList … … 31 30 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 32 31 #include "Resolver.h" 32 #include "ResolvMode.h" // for ResolvMode 33 33 #include "SymTab/Autogen.h" // for SizeType 34 34 #include "SymTab/Indexer.h" // for Indexer … … 168 168 169 169 namespace { 170 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {170 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) { 171 171 assertf( untyped, "expected a non-null expression." ); 172 173 // xxx - this isn't thread-safe, but should work until we parallelize the resolver 174 static unsigned recursion_level = 0; 175 176 ++recursion_level; 172 177 TypeEnvironment env; 173 178 AlternativeFinder finder( indexer, env ); 174 finder.find( untyped, adjust, prune, failFast ); 179 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 180 --recursion_level; 175 181 176 182 #if 0 … … 185 191 #endif 186 192 193 // produce filtered list of alternatives 187 194 AltList candidates; 188 195 for ( Alternative & alt : finder.get_alternatives() ) { … … 192 199 } 193 200 194 // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining 195 // choose the lowest cost expression among the candidates 201 // produce invalid error if no candidates 202 if ( candidates.empty() ) { 203 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") ); 204 } 205 206 // search for cheapest candidate 196 207 AltList winners; 197 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 198 if ( winners.size() == 0 ) { 199 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") ); 200 } else if ( winners.size() != 1 ) { 208 bool seen_undeleted = false; 209 for ( unsigned i = 0; i < candidates.size(); ++i ) { 210 int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost ); 211 212 if ( c > 0 ) continue; // skip more expensive than winner 213 214 if ( c < 0 ) { 215 // reset on new cheapest 216 seen_undeleted = ! findDeletedExpr( candidates[i].expr ); 217 winners.clear(); 218 } else /* if ( c == 0 ) */ { 219 if ( findDeletedExpr( candidates[i].expr ) ) { 220 // skip deleted expression if already seen one equivalent-cost not 221 if ( seen_undeleted ) continue; 222 } else if ( ! seen_undeleted ) { 223 // replace list of equivalent-cost deleted expressions with one non-deleted 224 winners.clear(); 225 seen_undeleted = true; 226 } 227 } 228 229 winners.emplace_back( std::move( candidates[i] ) ); 230 } 231 232 // promote alternative.cvtCost to .cost 233 // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost 234 for ( Alternative& winner : winners ) { 235 winner.cost = winner.cvtCost; 236 } 237 238 // produce ambiguous errors, if applicable 239 if ( winners.size() != 1 ) { 201 240 std::ostringstream stream; 202 241 stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n"; … … 207 246 } 208 247 209 // there is one unambiguous interpretation - move the expression into the with statement 210 Alternative & choice = winners.front(); 211 if ( findDeletedExpr( choice.expr ) ) { 248 // single selected choice 249 Alternative& choice = winners.front(); 250 251 // fail on only expression deleted 252 if ( ! seen_undeleted ) { 212 253 SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " ); 213 254 } 255 256 // xxx - check for ambiguous expressions 257 258 // output selected choice 214 259 alt = std::move( choice ); 215 260 } 216 261 217 262 /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages 218 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {263 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) { 219 264 if ( ! untyped ) return; 220 265 Alternative choice; 221 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast);266 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode ); 222 267 finishExpr( choice.expr, choice.env, untyped->env ); 223 268 delete untyped; … … 250 295 untyped.arg = expr; 251 296 Alternative choice; 252 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true);297 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() ); 253 298 CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr ); 254 299 env = std::move( choice.env ); … … 357 402 358 403 void Resolver::previsit( ObjectDecl *objectDecl ) { 359 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable360 // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes361 // initContext because of a function type can contain object declarations in the return and parameter types. So362 // each value of initContext is retained, so the type on the first analysis is preserved and used for selecting363 // the RHS.404 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that 405 // class-variable initContext is changed multiple time because the LHS is analysed twice. 406 // The second analysis changes initContext because of a function type can contain object 407 // declarations in the return and parameter types. So each value of initContext is 408 // retained, so the type on the first analysis is preserved and used for selecting the RHS. 364 409 GuardValue( currentObject ); 365 410 currentObject = CurrentObject( objectDecl->get_type() ); … … 397 442 398 443 void Resolver::postvisit( FunctionDecl *functionDecl ) { 399 // default value expressions have an environment which shouldn't be there and trips up later passes. 400 // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently 401 // see how it's useful. 444 // default value expressions have an environment which shouldn't be there and trips up 445 // later passes. 446 // xxx - it might be necessary to somehow keep the information from this environment, but I 447 // can't currently see how it's useful. 402 448 for ( Declaration * d : functionDecl->type->parameters ) { 403 449 if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) { … … 749 795 initExpr->expr = nullptr; 750 796 std::swap( initExpr->env, newExpr->env ); 751 // InitExpr may have inferParams in the case where the expression specializes a function pointer, 752 // and newExpr may already have inferParams of its own, so a simple swap is not sufficient. 797 // InitExpr may have inferParams in the case where the expression specializes a function 798 // pointer, and newExpr may already have inferParams of its own, so a simple swap is not 799 // sufficient. 753 800 newExpr->spliceInferParams( initExpr ); 754 801 delete initExpr; 755 802 756 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions) 803 // get the actual object's type (may not exactly match what comes back from the resolver 804 // due to conversions) 757 805 Type * initContext = currentObject.getCurrentType(); 758 806 … … 766 814 if ( isCharType( pt->get_base() ) ) { 767 815 if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) { 768 // strip cast if we're initializing a char[] with a char *, e.g. char x[] = "hello"; 816 // strip cast if we're initializing a char[] with a char *, 817 // e.g. char x[] = "hello"; 769 818 newExpr = ce->get_arg(); 770 819 ce->set_arg( nullptr ); … … 788 837 // move cursor into brace-enclosed initializer-list 789 838 currentObject.enterListInit(); 790 // xxx - fix this so that the list isn't copied, iterator should be used to change current element 839 // xxx - fix this so that the list isn't copied, iterator should be used to change current 840 // element 791 841 std::list<Designation *> newDesignations; 792 842 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) { 793 // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving794 // the initializer against that object.843 // iterate designations and initializers in pairs, moving the cursor to the current 844 // designated object and resolving the initializer against that object. 795 845 Designation * des = std::get<0>(p); 796 846 Initializer * init = std::get<1>(p); … … 822 872 // fall back on C-style initializer 823 873 delete ctorInit->get_ctor(); 824 ctorInit->set_ctor( NULL);874 ctorInit->set_ctor( nullptr ); 825 875 delete ctorInit->get_dtor(); 826 ctorInit->set_dtor( NULL);876 ctorInit->set_dtor( nullptr ); 827 877 maybeAccept( ctorInit->get_init(), *visitor ); 828 878 } … … 867 917 868 918 // xxx - todo -- what about arrays? 869 // if ( dtor == NULL&& InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {919 // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) { 870 920 // // can reduce the constructor down to a SingleInit using the 871 921 // // second argument from the ctor call, since 872 922 // delete ctorInit->get_ctor(); 873 // ctorInit->set_ctor( NULL);923 // ctorInit->set_ctor( nullptr ); 874 924 875 925 // Expression * arg = -
src/ResolvExpr/TypeEnvironment.cc
r07ec1a2 r276a55b2 120 120 121 121 const EqvClass* TypeEnvironment::lookup( const std::string &var ) const { 122 for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {122 for ( ClassList::const_iterator i = env.begin(); i != env.end(); ++i ) { 123 123 if ( i->vars.find( var ) != i->vars.end() ) return &*i; 124 124 } // for … … 168 168 169 169 void TypeEnvironment::makeSubstitution( TypeSubstitution &sub ) const { 170 for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {170 for ( ClassList::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) { 171 171 for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) { 172 172 if ( theClass->type ) { … … 188 188 } 189 189 190 std::list< EqvClass >::iterator TypeEnvironment::internal_lookup( const std::string &var ) {191 for ( std::list< EqvClass >::iterator i = env.begin(); i != env.end(); ++i ) {190 TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const std::string &var ) { 191 for ( ClassList::iterator i = env.begin(); i != env.end(); ++i ) { 192 192 if ( i->vars.count( var ) ) return i; 193 193 } // for … … 199 199 } 200 200 201 // xxx -- this should maybe be worrying about iterator invalidation (see resolv-proto) 202 bool TypeEnvironment::mergeBound( EqvClass& to, const EqvClass& from, OpenVarSet& openVars, const SymTab::Indexer& indexer ) { 203 if ( from.type ) { 204 if ( to.type ) { 205 // attempt to unify bound types 206 std::unique_ptr<Type> toType{ to.type->clone() }, fromType{ from.type->clone() }; 207 WidenMode widenMode{ to.allowWidening, from.allowWidening }; 208 Type* common = nullptr; 209 AssertionSet need, have; 210 if ( unifyInexact( toType.get(), fromType.get(), *this, need, have, openVars, widenMode, indexer, common ) ) { 211 // unifies, set common type if necessary 212 if ( common ) { 213 common->get_qualifiers() = Type::Qualifiers{}; 214 to.set_type( common ); 215 } 216 } else return false; // cannot unify 217 } else { 218 to.type = from.type->clone(); 219 } 220 } 221 222 // unify widening if matches 223 to.allowWidening &= from.allowWidening; 224 return true; 225 } 226 227 // xxx -- this should maybe be worrying about iterator invalidation (see resolv-proto) 228 bool TypeEnvironment::mergeClasses( TypeEnvironment::ClassList::iterator to, TypeEnvironment::ClassList::iterator from, OpenVarSet& openVars, const SymTab::Indexer& indexer ) { 229 EqvClass& r = *to; 230 EqvClass& s = *from; 231 232 // ensure bounds match 233 if ( ! mergeBound( r, s, openVars, indexer ) ) return false; 234 235 // check safely bindable 236 if ( r.type && occursIn( r.type, s.vars.begin(), s.vars.end(), *this ) ) return false; 237 238 // merge classes in 239 r.vars.insert( s.vars.begin(), s.vars.end() ); 240 r.allowWidening &= s.allowWidening; 241 env.erase( from ); 242 243 return true; 244 } 245 246 bool TypeEnvironment::combine( const TypeEnvironment& o, OpenVarSet& openVars, const SymTab::Indexer& indexer ) { 247 // short-circuit easy cases 248 if ( o.isEmpty() ) return true; 249 if ( isEmpty() ) { 250 simpleCombine( o ); 251 return true; 252 } 253 254 // merge classes 255 for ( auto ct = o.env.begin(); ct != o.env.end(); ++ct ) { 256 const EqvClass& c = *ct; 257 258 // typeclass in local environment bound to c 259 auto rt = env.end(); 260 261 // look for first existing bound variable 262 auto vt = c.vars.begin(); 263 for ( ; vt != c.vars.end(); ++vt ) { 264 rt = internal_lookup( *vt ); 265 if ( rt != env.end() ) break; 266 } 267 268 if ( rt != env.end() ) { // c needs to be merged into *rt 269 EqvClass& r = *rt; 270 // merge bindings 271 if ( ! mergeBound( r, c, openVars, indexer ) ) return false; 272 // merge previous unbound variables into this class, checking occurs if needed 273 if ( r.type ) for ( auto ut = c.vars.begin(); ut != vt; ++ut ) { 274 if ( occurs( r.type, *ut, *this ) ) return false; 275 r.vars.insert( *ut ); 276 } else { r.vars.insert( c.vars.begin(), vt ); } 277 // merge subsequent variables into this class (skipping *vt, already there) 278 while ( ++vt != c.vars.end() ) { 279 auto st = internal_lookup( *vt ); 280 if ( st == env.end() ) { 281 // unbound, safe to add if passes occurs 282 if ( r.type && occurs( r.type, *vt, *this ) ) return false; 283 r.vars.insert( *vt ); 284 } else if ( st != rt ) { 285 // bound, but not to the same class 286 if ( ! mergeClasses( rt, st, openVars, indexer ) ) return false; 287 } // ignore bound into the same class 288 } 289 } else { // no variables in c bound; just copy up 290 env.push_back( c ); 291 } 292 } 293 294 // merged all classes 295 return true; 296 } 297 201 298 void TypeEnvironment::extractOpenVars( OpenVarSet &openVars ) const { 202 for ( std::list< EqvClass >::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) {299 for ( ClassList::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) { 203 300 for ( std::set< std::string >::const_iterator var = eqvClass->vars.begin(); var != eqvClass->vars.end(); ++var ) { 204 301 openVars[ *var ] = eqvClass->data; -
src/ResolvExpr/TypeEnvironment.h
r07ec1a2 r276a55b2 39 39 // declarations. 40 40 // 41 // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator. 41 // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this 42 // comparator. 42 43 // 43 44 // Note: since this compares pointers for position, minor changes in the source file that affect 44 45 // memory layout can alter compilation time in unpredictable ways. For example, the placement 45 46 // of a line directive can reorder type pointers with respect to each other so that assertions 46 // are seen in different orders, causing a potentially different number of unification calls when 47 // resolving assertions. I've seen a TU go from 36 seconds to 27 seconds by reordering line directives 48 // alone, so it would be nice to fix this comparison so that assertions compare more consistently. 49 // I've tried to modify this to compare on mangle name instead of type as the second comparator, but 50 // this causes some assertions to never be recorded. More investigation is needed. 47 // are seen in different orders, causing a potentially different number of unification calls 48 // when resolving assertions. I've seen a TU go from 36 seconds to 27 seconds by reordering 49 // line directives alone, so it would be nice to fix this comparison so that assertions compare 50 // more consistently. I've tried to modify this to compare on mangle name instead of type as 51 // the second comparator, but this causes some assertions to never be recorded. More 52 // investigation is needed. 51 53 struct AssertCompare { 52 54 bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const { … … 57 59 }; 58 60 struct AssertionSetValue { 59 bool isUsed; 60 // chain of Unique IDs of the assertion declarations. The first ID in the chain is the ID of an assertion on the current type, 61 // with each successive ID being the ID of an assertion pulled in by the previous ID. The last ID in the chain is 62 // the ID of the assertion that pulled in the current assertion. 63 std::list< UniqueId > idChain; 61 bool isUsed; ///< True if assertion needs to be resolved 62 UniqueId resnSlot; ///< ID of slot assertion belongs to 63 64 AssertionSetValue() : isUsed(false), resnSlot(0) {} 64 65 }; 65 66 typedef std::map< DeclarationWithType*, AssertionSetValue, AssertCompare > AssertionSet; 66 67 typedef std::map< std::string, TypeDecl::Data > OpenVarSet; 68 69 /// merges one set of open vars into another 70 static inline void mergeOpenVars( OpenVarSet& dst, const OpenVarSet& src ) { 71 for ( const auto& entry : src ) { dst[ entry.first ] = entry.second; } 72 } 67 73 68 74 void printAssertionSet( const AssertionSet &, std::ostream &, int indent = 0 ); … … 91 97 92 98 class TypeEnvironment { 99 using ClassList = std::list< EqvClass >; 93 100 public: 94 101 const EqvClass* lookup( const std::string &var ) const; … … 103 110 bool isEmpty() const { return env.empty(); } 104 111 void print( std::ostream &os, Indenter indent = {} ) const; 105 // void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) ); 112 113 /// Simply concatenate the second environment onto this one; no safety checks performed 106 114 void simpleCombine( const TypeEnvironment &second ); 115 116 private: 117 /// Unifies the type bound of to with the type bound of from, returning false if fails 118 bool mergeBound( EqvClass& to, const EqvClass& from, OpenVarSet& openVars, const SymTab::Indexer& indexer ); 119 120 /// Merges two type classes from local environment, returning false if fails 121 bool mergeClasses( ClassList::iterator to, ClassList::iterator from, OpenVarSet& openVars, const SymTab::Indexer& indexer ); 122 123 public: 124 /// Merges the second environment with this one, checking compatibility. 125 /// Returns false if fails, but does NOT roll back partial changes. 126 bool combine( const TypeEnvironment& second, OpenVarSet& openVars, const SymTab::Indexer& indexer ); 127 107 128 void extractOpenVars( OpenVarSet &openVars ) const; 108 129 TypeEnvironment *clone() const { return new TypeEnvironment( *this ); } … … 123 144 void forbidWidening(); 124 145 125 using iterator = std::list< EqvClass >::const_iterator;146 using iterator = ClassList::const_iterator; 126 147 iterator begin() const { return env.begin(); } 127 148 iterator end() const { return env.end(); } 128 149 129 150 private: 130 std::list< EqvClass >env;151 ClassList env; 131 152 132 std::list< EqvClass >::iterator internal_lookup( const std::string &var );153 ClassList::iterator internal_lookup( const std::string &var ); 133 154 }; 134 155 -
src/ResolvExpr/module.mk
r07ec1a2 r276a55b2 33 33 ResolvExpr/TypeEnvironment.cc \ 34 34 ResolvExpr/CurrentObject.cc \ 35 ResolvExpr/ExplodedActual.cc 35 ResolvExpr/ExplodedActual.cc \ 36 ResolvExpr/SpecCost.cc \ 37 ResolvExpr/ResolveAssertions.cc -
src/ResolvExpr/typeops.h
r07ec1a2 r276a55b2 72 72 Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 73 73 74 // in AlternativeFinder.cc 75 Cost computeConversionCost( Type *actualType, Type *formalType, 76 const SymTab::Indexer &indexer, const TypeEnvironment &env ); 77 74 78 // in PtrsAssignable.cc 75 79 int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env ); … … 102 106 int polyCost( Type *type, const TypeEnvironment &env, const SymTab::Indexer &indexer ); 103 107 108 // in SpecCost.cc 109 int specCost( Type *type ); 110 104 111 // in Occurs.cc 105 112 bool occurs( Type *type, std::string varName, const TypeEnvironment &env ); 113 114 template<typename Iter> 115 bool occursIn( Type* ty, Iter begin, Iter end, const TypeEnvironment &env ) { 116 while ( begin != end ) { 117 if ( occurs( ty, *begin, env ) ) return true; 118 ++begin; 119 } 120 return false; 121 } 106 122 107 123 // in AlternativeFinder.cc -
src/SynTree/ApplicationExpr.cc
r07ec1a2 r276a55b2 29 29 30 30 ParamEntry::ParamEntry( const ParamEntry &other ) : 31 decl( other.decl ), actualType( maybeClone( other.actualType ) ), formalType( maybeClone( other.formalType ) ), expr( maybeClone( other.expr ) ) , inferParams( new InferredParams( *other.inferParams ) ){31 decl( other.decl ), actualType( maybeClone( other.actualType ) ), formalType( maybeClone( other.formalType ) ), expr( maybeClone( other.expr ) )/*, inferParams( new InferredParams( *other.inferParams ) )*/ { 32 32 } 33 33 … … 39 39 formalType = maybeClone( other.formalType ); 40 40 expr = maybeClone( other.expr ); 41 *inferParams = *other.inferParams;41 // *inferParams = *other.inferParams; 42 42 return *this; 43 43 } … … 50 50 51 51 ParamEntry::ParamEntry( ParamEntry && other ) : 52 decl( other.decl ), actualType( other.actualType ), formalType( other.formalType ), expr( other.expr ) , inferParams( std::move( other.inferParams ) ){52 decl( other.decl ), actualType( other.actualType ), formalType( other.formalType ), expr( other.expr )/*, inferParams( std::move( other.inferParams ) )*/ { 53 53 other.actualType = nullptr; 54 54 other.formalType = nullptr; … … 68 68 other.formalType = nullptr; 69 69 other.expr = nullptr; 70 inferParams = std::move( other.inferParams );70 // inferParams = std::move( other.inferParams ); 71 71 return *this; 72 72 } -
src/SynTree/Expression.cc
r07ec1a2 r276a55b2 40 40 Declaration::declFromId( i->second.decl )->printShort( os, indent+1 ); 41 41 os << std::endl; 42 printInferParams( *i->second.inferParams, os, indent+1, level+1 );42 printInferParams( i->second.expr->inferParams, os, indent+1, level+1 ); 43 43 } // for 44 44 } // if … … 47 47 Expression::Expression() : result( 0 ), env( 0 ) {} 48 48 49 Expression::Expression( const Expression &other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), extension( other.extension ), inferParams( other.inferParams ) { 50 } 49 Expression::Expression( const Expression &other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), extension( other.extension ), inferParams( other.inferParams ), resnSlots( other.resnSlots ) {} 51 50 52 51 void Expression::spliceInferParams( Expression * other ) { … … 55 54 inferParams[p.first] = std::move( p.second ); 56 55 } 56 resnSlots.insert( resnSlots.end(), other->resnSlots.begin(), other->resnSlots.end() ); 57 57 } 58 58 -
src/SynTree/Expression.h
r07ec1a2 r276a55b2 21 21 #include <memory> // for allocator, unique_ptr 22 22 #include <string> // for string 23 #include <vector> // for vector 23 24 24 25 #include "BaseSyntaxNode.h" // for BaseSyntaxNode … … 38 39 /// but subject to decay-to-pointer and type parameter renaming 39 40 struct ParamEntry { 40 ParamEntry(): decl( 0 ), actualType( 0 ), formalType( 0 ), expr( 0 ) , inferParams( new InferredParams ){}41 ParamEntry( UniqueId decl, Type * actualType, Type * formalType, Expression* expr ): decl( decl ), actualType( actualType ), formalType( formalType ), expr( expr ) , inferParams( new InferredParams ){}41 ParamEntry(): decl( 0 ), actualType( 0 ), formalType( 0 ), expr( 0 )/*, inferParams( new InferredParams )*/ {} 42 ParamEntry( UniqueId decl, Type * actualType, Type * formalType, Expression* expr ): decl( decl ), actualType( actualType ), formalType( formalType ), expr( expr )/*, inferParams( new InferredParams )*/ {} 42 43 ParamEntry( const ParamEntry & other ); 43 44 ParamEntry( ParamEntry && other ); … … 50 51 Type * formalType; 51 52 Expression * expr; 52 std::unique_ptr< InferredParams > inferParams;53 // std::unique_ptr< InferredParams > inferParams; 53 54 }; 54 55 … … 59 60 TypeSubstitution * env; 60 61 bool extension = false; 61 InferredParams inferParams; 62 InferredParams inferParams; ///< Post-resolution inferred parameter slots 63 std::vector<UniqueId> resnSlots; ///< Pre-resolution inferred parameter slots 64 65 // xxx - should turn inferParams+resnSlots into a union to save some memory 62 66 63 67 Expression(); … … 73 77 bool get_extension() const { return extension; } 74 78 Expression * set_extension( bool exten ) { extension = exten; return this; } 75 76 InferredParams & get_inferParams() { return inferParams; }77 79 78 80 // move other's inferParams to this -
src/Tuples/Explode.h
r07ec1a2 r276a55b2 44 44 template<typename OutputIterator> 45 45 void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env, 46 const ResolvExpr::OpenVarSet& openVars, const ResolvExpr::AssertionList& need, 46 47 const ResolvExpr::Cost& cost, const ResolvExpr::Cost& cvtCost ) { 47 *out++ = ResolvExpr::Alternative{ expr, env, cost, cvtCost };48 *out++ = ResolvExpr::Alternative{ expr, env, openVars, need, cost, cvtCost }; 48 49 } 49 50 50 51 /// Append alternative to an ExplodedActual 51 52 static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr, 52 const ResolvExpr::TypeEnvironment&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) { 53 const ResolvExpr::TypeEnvironment&, const ResolvExpr::OpenVarSet&, 54 const ResolvExpr::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) { 53 55 ea.exprs.emplace_back( expr ); 54 /// xxx -- merge environment, cost?56 /// xxx -- merge environment, openVars, need, cost? 55 57 } 56 58 … … 68 70 // distribute reference cast over all components 69 71 append( std::forward<Output>(out), distributeReference( alt.release_expr() ), 70 alt.env, alt. cost, alt.cvtCost );72 alt.env, alt.openVars, alt.need, alt.cost, alt.cvtCost ); 71 73 } 72 74 // in tuple assignment, still need to handle the other cases, but only if not already handled here (don't want to output too many alternatives) … … 102 104 } else { 103 105 // atomic (non-tuple) type - output a clone of the expression in a new alternative 104 append( std::forward<Output>(out), expr->clone(), alt.env, alt.cost, alt.cvtCost ); 106 append( std::forward<Output>(out), expr->clone(), alt.env, alt.openVars, alt.need, 107 alt.cost, alt.cvtCost ); 105 108 } 106 109 } -
src/Tuples/TupleAssignment.cc
r07ec1a2 r276a55b2 62 62 struct Matcher { 63 63 public: 64 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const65 ResolvExpr::AltList& rhs );64 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, 65 const ResolvExpr::AltList& rhs ); 66 66 virtual ~Matcher() {} 67 67 68 virtual void match( std::list< Expression * > &out ) = 0; 68 69 ObjectDecl * newObject( UniqueName & namer, Expression * expr ); 70 71 void combineState( const ResolvExpr::Alternative& alt ) { 72 compositeEnv.simpleCombine( alt.env ); 73 ResolvExpr::mergeOpenVars( openVars, alt.openVars ); 74 cloneAll( alt.need, need ); 75 } 76 77 void combineState( const ResolvExpr::AltList& alts ) { 78 for ( const ResolvExpr::Alternative& alt : alts ) { combineState( alt ); } 79 } 80 69 81 ResolvExpr::AltList lhs, rhs; 70 82 TupleAssignSpotter &spotter; … … 72 84 std::list< ObjectDecl * > tmpDecls; 73 85 ResolvExpr::TypeEnvironment compositeEnv; 86 ResolvExpr::OpenVarSet openVars; 87 ResolvExpr::AssertionSet need; 74 88 }; 75 89 … … 245 259 } 246 260 247 // extract expressions from the assignment alternatives to produce a list of assignments that248 // t ogether form a single alternative261 // extract expressions from the assignment alternatives to produce a list of assignments 262 // that together form a single alternative 249 263 std::list< Expression *> solved_assigns; 250 264 for ( ResolvExpr::Alternative & alt : current ) { 251 265 solved_assigns.push_back( alt.expr->clone() ); 252 }253 // combine assignment environments into combined expression environment254 simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv );266 matcher->combineState( alt ); 267 } 268 255 269 // xxx -- was push_front 256 currentFinder.get_alternatives().push_back( ResolvExpr::Alternative( 257 new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv, 258 ResolvExpr::sumCost( current ) + matcher->baseCost ) ); 270 currentFinder.get_alternatives().push_back( ResolvExpr::Alternative{ 271 new TupleAssignExpr{ solved_assigns, matcher->tmpDecls }, matcher->compositeEnv, 272 matcher->openVars, 273 ResolvExpr::AssertionList( matcher->need.begin(), matcher->need.end() ), 274 ResolvExpr::sumCost( current ) + matcher->baseCost } ); 259 275 } 260 276 … … 263 279 : lhs(lhs), rhs(rhs), spotter(spotter), 264 280 baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) { 265 simpleCombineEnvironments( lhs.begin(), lhs.end(), compositeEnv );266 simpleCombineEnvironments( rhs.begin(), rhs.end(), compositeEnv);281 combineState( lhs ); 282 combineState( rhs ); 267 283 } 268 284 -
tests/.expect/castError.txt
r07ec1a2 r276a55b2 4 4 ... to: 5 5 char Alternatives are: 6 Cost ( 1, 0, 0, 0 ): Cast of:6 Cost ( 1, 0, 0, 0, 0, 0 ): Cast of: 7 7 Variable Expression: f: function 8 8 accepting unspecified arguments … … 16 16 Environment: 17 17 18 Cost ( 1, 0, 0, 0 ): Cast of:18 Cost ( 1, 0, 0, 0, 0, 0 ): Cast of: 19 19 Variable Expression: f: double 20 20 ... to: … … 25 25 Environment: 26 26 27 Cost ( 1, 0, 0, 0 ): Cast of:27 Cost ( 1, 0, 0, 0, 0, 0 ): Cast of: 28 28 Variable Expression: f: signed int 29 29 ... to: -
tests/searchsort.cfa
r07ec1a2 r276a55b2 57 57 58 58 // descending sort/search by changing < to > 59 for ( i; 0 u~ size ) {59 for ( i; 0 ~ size ) { 60 60 iarr[i] = i + 1; 61 61 sout | iarr[i] | ", ";
Note: See TracChangeset
for help on using the changeset viewer.