Changes in / [276a55b2:07ec1a2]
- Files:
-
- 5 deleted
- 23 edited
-
src/Common/FilterCombos.h (deleted)
-
src/Common/utility.h (modified) (2 diffs)
-
src/GenPoly/Box.cc (modified) (1 diff)
-
src/GenPoly/Specialize.cc (modified) (3 diffs)
-
src/Makefile.am (modified) (1 diff)
-
src/Makefile.in (modified) (6 diffs)
-
src/ResolvExpr/Alternative.cc (modified) (6 diffs)
-
src/ResolvExpr/Alternative.h (modified) (3 diffs)
-
src/ResolvExpr/AlternativeFinder.cc (modified) (48 diffs)
-
src/ResolvExpr/AlternativeFinder.h (modified) (3 diffs)
-
src/ResolvExpr/ConversionCost.cc (modified) (1 diff)
-
src/ResolvExpr/Cost.h (modified) (12 diffs)
-
src/ResolvExpr/ResolvMode.h (deleted)
-
src/ResolvExpr/ResolveAssertions.cc (deleted)
-
src/ResolvExpr/ResolveAssertions.h (deleted)
-
src/ResolvExpr/Resolver.cc (modified) (14 diffs)
-
src/ResolvExpr/SpecCost.cc (deleted)
-
src/ResolvExpr/TypeEnvironment.cc (modified) (4 diffs)
-
src/ResolvExpr/TypeEnvironment.h (modified) (5 diffs)
-
src/ResolvExpr/module.mk (modified) (1 diff)
-
src/ResolvExpr/typeops.h (modified) (2 diffs)
-
src/SynTree/ApplicationExpr.cc (modified) (4 diffs)
-
src/SynTree/Expression.cc (modified) (3 diffs)
-
src/SynTree/Expression.h (modified) (5 diffs)
-
src/Tuples/Explode.h (modified) (3 diffs)
-
src/Tuples/TupleAssignment.cc (modified) (4 diffs)
-
tests/.expect/castError.txt (modified) (3 diffs)
-
tests/searchsort.cfa (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/Common/utility.h
r276a55b2 r07ec1a2 26 26 #include <string> 27 27 #include <type_traits> 28 #include <utility>29 28 30 29 #include <cassert> … … 463 462 std::pair<long long int, bool> eval(Expression * expr); 464 463 465 // -----------------------------------------------------------------------------466 /// Reorders the input range in-place so that the minimal-value elements according to the467 /// 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 position477 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 position481 ++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::less494 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 499 464 // Local Variables: // 500 465 // tab-width: 4 // -
src/GenPoly/Box.cc
r276a55b2 r07ec1a2 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-> 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() );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() ); 802 802 Expression *newExpr = inferParam->second.expr->clone(); 803 803 addCast( newExpr, (*assert)->get_type(), tyVars ); -
src/GenPoly/Specialize.cc
r276a55b2 r07ec1a2 245 245 appExpr->env = TypeSubstitution::newFromExpr( appExpr, env ); 246 246 if ( inferParams ) { 247 appExpr-> inferParams= *inferParams;247 appExpr->get_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-> inferParams);286 *actual = doSpecialization( (*formal)->get_type(), *actual, &appExpr->get_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-> inferParams.begin(); inferParam != appExpr->inferParams.end(); ++inferParam ) {298 inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &inferParam->second.expr->inferParams);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() ); 299 299 } 300 300 } -
src/Makefile.am
r276a55b2 r07ec1a2 127 127 ResolvExpr/PtrsCastable.cc \ 128 128 ResolvExpr/RenameVars.cc \ 129 ResolvExpr/ResolveAssertions.cc \130 129 ResolvExpr/Resolver.cc \ 131 130 ResolvExpr/ResolveTypeof.cc \ 132 ResolvExpr/SpecCost.cc \133 131 ResolvExpr/TypeEnvironment.cc \ 134 132 ResolvExpr/Unify.cc \ -
src/Makefile.in
r276a55b2 r07ec1a2 206 206 ResolvExpr/PtrsAssignable.$(OBJEXT) \ 207 207 ResolvExpr/PtrsCastable.$(OBJEXT) \ 208 ResolvExpr/RenameVars.$(OBJEXT) \ 209 ResolvExpr/ResolveAssertions.$(OBJEXT) \ 210 ResolvExpr/Resolver.$(OBJEXT) \ 208 ResolvExpr/RenameVars.$(OBJEXT) ResolvExpr/Resolver.$(OBJEXT) \ 211 209 ResolvExpr/ResolveTypeof.$(OBJEXT) \ 212 ResolvExpr/SpecCost.$(OBJEXT) \213 210 ResolvExpr/TypeEnvironment.$(OBJEXT) \ 214 211 ResolvExpr/Unify.$(OBJEXT) SymTab/Autogen.$(OBJEXT) \ … … 265 262 ResolvExpr/TypeEnvironment.$(OBJEXT) \ 266 263 ResolvExpr/CurrentObject.$(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) \ 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) \ 277 271 SynTree/ReferenceToType.$(OBJEXT) SynTree/TupleType.$(OBJEXT) \ 278 272 SynTree/TypeofType.$(OBJEXT) SynTree/AttrType.$(OBJEXT) \ … … 595 589 ResolvExpr/Occurs.cc ResolvExpr/TypeEnvironment.cc \ 596 590 ResolvExpr/CurrentObject.cc ResolvExpr/ExplodedActual.cc \ 597 ResolvExpr/SpecCost.cc ResolvExpr/ResolveAssertions.cc \598 591 SymTab/Indexer.cc SymTab/Mangler.cc SymTab/ManglerCommon.cc \ 599 592 SymTab/Validate.cc SymTab/FixFunction.cc SymTab/Autogen.cc \ … … 703 696 ResolvExpr/PtrsCastable.cc \ 704 697 ResolvExpr/RenameVars.cc \ 705 ResolvExpr/ResolveAssertions.cc \706 698 ResolvExpr/Resolver.cc \ 707 699 ResolvExpr/ResolveTypeof.cc \ 708 ResolvExpr/SpecCost.cc \709 700 ResolvExpr/TypeEnvironment.cc \ 710 701 ResolvExpr/Unify.cc \ … … 955 946 ResolvExpr/RenameVars.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 956 947 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 957 ResolvExpr/ResolveAssertions.$(OBJEXT): ResolvExpr/$(am__dirstamp) \958 ResolvExpr/$(DEPDIR)/$(am__dirstamp)959 948 ResolvExpr/Resolver.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 960 949 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 961 950 ResolvExpr/ResolveTypeof.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ 962 ResolvExpr/$(DEPDIR)/$(am__dirstamp)963 ResolvExpr/SpecCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \964 951 ResolvExpr/$(DEPDIR)/$(am__dirstamp) 965 952 ResolvExpr/TypeEnvironment.$(OBJEXT): ResolvExpr/$(am__dirstamp) \ … … 1220 1207 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/PtrsCastable.Po@am__quote@ 1221 1208 @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@1223 1209 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ResolveTypeof.Po@am__quote@ 1224 1210 @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@1226 1211 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/TypeEnvironment.Po@am__quote@ 1227 1212 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Unify.Po@am__quote@ -
src/ResolvExpr/Alternative.cc
r276a55b2 r07ec1a2 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:44:23 2015 11 // Last Modified By : Aaron B. Moss12 // Last Modified On : Thu Oct 11 10:55:00 201813 // Update Count : 311 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat May 16 23:54:23 2015 13 // Update Count : 2 14 14 // 15 15 … … 20 20 #include <utility> // for move 21 21 22 #include "Common/utility.h" // for cloneAll22 #include "Common/utility.h" // for maybeClone 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() 30 : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ), env(), openVars(), need() {} 29 Alternative::Alternative() : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ) {} 31 30 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 ); } 31 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost ) 32 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ) {} 38 33 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 ); } 34 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost, const Cost &cvtCost ) 35 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {} 43 36 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 ); } 37 Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) { 38 } 74 39 75 40 Alternative &Alternative::operator=( const Alternative &other ) { … … 80 45 expr = maybeClone( other.expr ); 81 46 env = other.env; 82 openVars = other.openVars;83 need.clear();84 cloneAll( other.need, need );85 47 return *this; 86 48 } 87 49 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; } 50 Alternative::Alternative( Alternative && other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), env( std::move( other.env ) ) { 51 other.expr = nullptr; 52 } 92 53 93 54 Alternative & Alternative::operator=( Alternative && other ) { … … 98 59 expr = other.expr; 99 60 env = std::move( other.env ); 100 openVars = std::move( other.openVars );101 need = std::move( other.need );102 61 other.expr = nullptr; 103 62 return *this; … … 105 64 106 65 Alternative::~Alternative() { 107 for ( AssertionItem& n : need ) { delete n.decl; }108 66 delete expr; 109 67 } -
src/ResolvExpr/Alternative.h
r276a55b2 r07ec1a2 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:45:43 2015 11 // Last Modified By : Aaron B. Moss12 // Last Modified On : Thu Oct 11 10:55:00 201813 // Update Count : 411 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 22 09:36:36 2017 13 // Update Count : 3 14 14 // 15 15 … … 20 20 21 21 #include "Cost.h" // for Cost 22 #include "TypeEnvironment.h" // for TypeEnvironment, AssertionSetValue 23 24 #include "Common/utility.h" // for maybeClone 22 #include "TypeEnvironment.h" // for TypeEnvironment 25 23 26 24 class Expression; 27 25 28 26 namespace ResolvExpr { 29 /// One assertion to resolve30 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 cloneAll41 AssertionItem clone() const { return { maybeClone(decl), info }; }42 };43 /// A list of unresolved assertions44 using AssertionList = std::vector<AssertionItem>;45 46 /// Clones an assertion list into an assertion set47 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 list54 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 list62 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 expression70 27 struct Alternative { 71 28 Alternative(); 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 ); 29 Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost ); 30 Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost, const Cost &cvtCost ); 86 31 Alternative( const Alternative &other ); 87 32 Alternative &operator=( const Alternative &other ); … … 99 44 } 100 45 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 46 Cost cost; 47 Cost cvtCost; 48 Expression *expr; 49 TypeEnvironment env; 110 50 }; 111 51 -
src/ResolvExpr/AlternativeFinder.cc
r276a55b2 r07ec1a2 11 11 // Last Modified By : Peter A. Buhr 12 12 // Last Modified On : Thu Nov 1 21:00:56 2018 13 // Update Count : 3 513 // Update Count : 34 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 resolveAssertions37 36 #include "ResolveTypeof.h" // for resolveTypeof 38 37 #include "Resolver.h" // for resolveStmtExpr … … 103 102 void addAnonConversions( const Alternative & alt ); 104 103 /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member 105 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative &alt, const Cost &newCost, const std::string & name );104 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ); 106 105 /// Adds alternatives for member expressions where the left side has tuple type 107 void addTupleMembers( TupleType * tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member );106 void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ); 108 107 /// Adds alternatives for offsetof expressions, given the base type and name of the member 109 108 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name ); … … 114 113 template<typename OutputIterator> 115 114 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out ); 116 /// Sets up parameter inference for an outputalternative115 /// Checks if assertion parameters match for a new alternative 117 116 template< typename OutputIterator > 118 void inferParameters( Alternative &newAlt, OutputIterator out );117 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ); 119 118 private: 120 119 AlternativeFinder & altFinder; … … 245 244 } 246 245 247 void AlternativeFinder::find( Expression *expr, ResolvMode mode) {246 void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) { 248 247 PassVisitor<Finder> finder( *this ); 249 248 expr->accept( finder ); 250 if ( mode.failFast && alternatives.empty() ) {249 if ( failFast && alternatives.empty() ) { 251 250 PRINT( 252 251 std::cerr << "No reasonable alternatives for expression " << expr << std::endl; … … 254 253 SemanticError( expr, "No reasonable alternatives for expression " ); 255 254 } 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 ) { 255 if ( prune ) { 275 256 auto oldsize = alternatives.size(); 276 257 PRINT( … … 280 261 AltList pruned; 281 262 pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) ); 282 if ( mode.failFast && pruned.empty() ) {263 if ( failFast && pruned.empty() ) { 283 264 std::ostringstream stream; 284 265 AltList winners; … … 299 280 } 300 281 // adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted 301 if ( mode.adjust) {302 for ( Alternative& i : alternatives) {303 adjustExprType( i .expr->get_result(), i.env, indexer );282 for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) { 283 if ( adjust ) { 284 adjustExprType( i->expr->get_result(), i->env, indexer ); 304 285 } 305 286 } … … 313 294 314 295 void AlternativeFinder::findWithAdjustment( Expression *expr ) { 315 find( expr, ResolvMode::withAdjustment());296 find( expr, true ); 316 297 } 317 298 318 299 void AlternativeFinder::findWithoutPrune( Expression * expr ) { 319 find( expr, ResolvMode::withoutPrune());300 find( expr, true, false ); 320 301 } 321 302 322 303 void AlternativeFinder::maybeFind( Expression * expr ) { 323 find( expr, ResolvMode::withoutFailFast());304 find( expr, true, true, false ); 324 305 } 325 306 … … 336 317 337 318 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) { 338 addAggMembers( structInst, aggrExpr.get(), alt , alt.cost+Cost::safe, "" );319 addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" ); 339 320 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) { 340 addAggMembers( unionInst, aggrExpr.get(), alt , alt.cost+Cost::safe, "" );321 addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" ); 341 322 } // if 342 323 } 343 324 344 325 template< typename StructOrUnionType > 345 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative& alt, const Cost &newCost, const std::string & name ) {326 void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) { 346 327 std::list< Declaration* > members; 347 328 aggInst->lookup( name, members ); … … 351 332 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 352 333 // can't construct in place and use vector::back 353 Alternative newAlt { alt, new MemberExpr{ dwt, expr->clone() }, newCost };334 Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost ); 354 335 renameTypes( newAlt.expr ); 355 336 addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression. … … 361 342 } 362 343 363 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member ) {344 void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) { 364 345 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) { 365 346 // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning … … 367 348 std::string tmp; 368 349 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 369 alternatives.push_back( Alternative{ 370 alt, new TupleIndexExpr( expr->clone(), val ), newCost } ); 350 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) ); 371 351 } // if 372 352 } // if … … 374 354 375 355 void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) { 376 alternatives.push_back( Alternative { applicationExpr->clone(), env });356 alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) ); 377 357 } 378 358 … … 430 410 Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) { 431 411 ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( alt.expr ); 432 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr-> function->result);433 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer-> base);412 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 413 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() ); 434 414 435 415 Cost convCost = Cost::zero; 436 std::list< DeclarationWithType* >& formals = function-> parameters;416 std::list< DeclarationWithType* >& formals = function->get_parameters(); 437 417 std::list< DeclarationWithType* >::iterator formal = formals.begin(); 438 std::list< Expression* >& actuals = appExpr-> args;439 440 for ( Expression*& actualExpr : actuals) {441 Type * actualType = actualExpr->result;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(); 442 422 PRINT( 443 423 std::cerr << "actual expression:" << std::endl; 444 actualExpr->print( std::cerr, 8 );424 (*actualExpr)->print( std::cerr, 8 ); 445 425 std::cerr << "--- results are" << std::endl; 446 426 actualType->print( std::cerr, 8 ); 447 427 ) 448 428 if ( formal == formals.end() ) { 449 if ( function-> isVarArgs) {429 if ( function->get_isVarArgs() ) { 450 430 convCost.incUnsafe(); 451 431 PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; ) 452 432 // convert reference-typed expressions to value-typed expressions 453 referenceToRvalueConversion( actualExpr, convCost );433 referenceToRvalueConversion( *actualExpr, convCost ); 454 434 continue; 455 435 } else { … … 457 437 } 458 438 } 459 if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( actualExpr ) ) {439 if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) { 460 440 // default arguments should be free - don't include conversion cost. 461 441 // Unwrap them here because they are not relevant to the rest of the system. 462 actualExpr = def->expr;442 *actualExpr = def->expr; 463 443 ++formal; 464 444 continue; 465 445 } 466 // mark conversion cost to formal and also specialization cost of formal type467 446 Type * formalType = (*formal)->get_type(); 468 convCost += computeExpressionConversionCost( actualExpr, formalType, indexer, alt.env ); 469 convCost.decSpec( specCost( formalType ) ); 447 convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env ); 470 448 ++formal; // can't be in for-loop update because of the continue 471 449 } … … 474 452 } 475 453 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 ) { 454 for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) { 489 455 convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env ); 490 456 } … … 500 466 needAssertions[ *assert ].isUsed = true; 501 467 } 502 } 503 } 504 505 /// Unique identifier for matching expression resolutions to their requesting expression 506 UniqueId globalResnSlot = 0; 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 } 507 585 508 586 template< typename OutputIterator > 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; 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 // ) 525 613 } 526 614 … … 863 951 } 864 952 // build and validate new alternative 865 Alternative newAlt { appExpr, result.env, result.openVars, result.need, cost };953 Alternative newAlt( appExpr, result.env, cost ); 866 954 PRINT( 867 955 std::cerr << "instantiate function success: " << appExpr << std::endl; … … 869 957 printAssertionSet( result.need, std::cerr, 8 ); 870 958 ) 871 inferParameters( newAlt, out );959 inferParameters( result.need, result.have, newAlt, result.openVars, out ); 872 960 } 873 961 … … 1114 1202 1115 1203 // function may return struct or union value, in which case we need to add alternatives 1116 // for implicit conversions to each of the anonymous members, must happen after findMinCost1204 // for implicitconversions to each of the anonymous members, must happen after findMinCost 1117 1205 // since anon conversions are never the cheapest expression 1118 1206 for ( const Alternative & alt : winners ) { … … 1146 1234 if ( isLvalue( alt.expr ) ) { 1147 1235 alternatives.push_back( 1148 Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } );1236 Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } ); 1149 1237 } // if 1150 1238 } // for … … 1152 1240 1153 1241 void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) { 1154 alternatives.push_back( Alternative{ expr->clone(), env } );1242 alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } ); 1155 1243 } 1156 1244 … … 1197 1285 AltList candidates; 1198 1286 for ( Alternative & alt : finder.alternatives ) { 1199 AssertionSet needAssertions( alt.need.begin(), alt.need.end() ); 1200 AssertionSet haveAssertions; 1201 OpenVarSet openVars{ alt.openVars }; 1287 AssertionSet needAssertions, haveAssertions; 1288 OpenVarSet openVars; 1202 1289 1203 1290 alt.env.extractOpenVars( openVars ); … … 1227 1314 // count one safe conversion for each value that is thrown away 1228 1315 thisCost.incSafe( discardedValues ); 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 ) );1316 Alternative newAlt( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env, 1317 alt.cost, thisCost ); 1318 inferParameters( needAssertions, haveAssertions, newAlt, openVars, 1319 back_inserter( candidates ) ); 1233 1320 } // if 1234 1321 } // for … … 1243 1330 1244 1331 void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) { 1245 assertf( castExpr->get_result(), "Implic itvirtual cast targets not yet supported." );1332 assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." ); 1246 1333 AlternativeFinder finder( indexer, env ); 1247 1334 // don't prune here, since it's guaranteed all alternatives will have the same type 1248 1335 finder.findWithoutPrune( castExpr->get_arg() ); 1249 1336 for ( Alternative & alt : finder.alternatives ) { 1250 alternatives.push_back( Alternative {1251 alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() },1252 alt. cost });1337 alternatives.push_back( Alternative( 1338 new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ), 1339 alt.env, alt.cost ) ); 1253 1340 } 1254 1341 } … … 1278 1365 // find member of the given type 1279 1366 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) { 1280 addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );1367 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) ); 1281 1368 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) { 1282 addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );1369 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) ); 1283 1370 } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) { 1284 addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() );1371 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() ); 1285 1372 } // if 1286 1373 } // for … … 1288 1375 1289 1376 void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) { 1290 alternatives.push_back( Alternative { memberExpr->clone(), env });1377 alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) ); 1291 1378 } 1292 1379 … … 1301 1388 // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so 1302 1389 // can't construct in place and use vector::back 1303 Alternative newAlt { newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost };1390 Alternative newAlt( newExpr, env, Cost::zero, cost ); 1304 1391 PRINT( 1305 1392 std::cerr << "decl is "; … … 1319 1406 // not sufficient to clone here, because variable's type may have changed 1320 1407 // since the VariableExpr was originally created. 1321 alternatives.push_back( Alternative { new VariableExpr{ variableExpr->var }, env });1408 alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) ); 1322 1409 } 1323 1410 1324 1411 void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) { 1325 alternatives.push_back( Alternative { constantExpr->clone(), env });1412 alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) ); 1326 1413 } 1327 1414 … … 1329 1416 if ( sizeofExpr->get_isType() ) { 1330 1417 Type * newType = sizeofExpr->get_type()->clone(); 1331 alternatives.push_back( Alternative{ 1332 new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1418 alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1333 1419 } else { 1334 1420 // find all alternatives for the argument to sizeof … … 1344 1430 Alternative &choice = winners.front(); 1345 1431 referenceToRvalueConversion( choice.expr, choice.cost ); 1346 alternatives.push_back( Alternative{ 1347 choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } ); 1432 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1348 1433 } // if 1349 1434 } … … 1352 1437 if ( alignofExpr->get_isType() ) { 1353 1438 Type * newType = alignofExpr->get_type()->clone(); 1354 alternatives.push_back( Alternative{ 1355 new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } ); 1439 alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) ); 1356 1440 } else { 1357 1441 // find all alternatives for the argument to sizeof … … 1367 1451 Alternative &choice = winners.front(); 1368 1452 referenceToRvalueConversion( choice.expr, choice.cost ); 1369 alternatives.push_back( Alternative{ 1370 choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } ); 1453 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1371 1454 } // if 1372 1455 } … … 1378 1461 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) { 1379 1462 if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) { 1380 alternatives.push_back( Alternative{ 1381 new OffsetofExpr{ aggInst->clone(), dwt }, env } ); 1463 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) ); 1382 1464 renameTypes( alternatives.back().expr ); 1383 1465 } else { … … 1398 1480 1399 1481 void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) { 1400 alternatives.push_back( Alternative { offsetofExpr->clone(), env });1482 alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) ); 1401 1483 } 1402 1484 1403 1485 void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) { 1404 alternatives.push_back( Alternative { offsetPackExpr->clone(), env });1486 alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) ); 1405 1487 } 1406 1488 … … 1422 1504 Cost cost = Cost::zero; 1423 1505 Expression * newExpr = data.combine( cost ); 1424 alternatives.push_back( Alternative{ 1425 new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{}, 1426 AssertionList{}, Cost::zero, cost } ); 1506 alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) ); 1427 1507 for ( DeclarationWithType * retVal : function->returnVals ) { 1428 1508 alternatives.back().expr->result = retVal->get_type()->clone(); … … 1463 1543 Cost cost = Cost::zero; 1464 1544 Expression * newExpr = data.combine( cost ); 1465 alternatives.push_back( Alternative{ 1466 newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost } ); 1545 alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) ); 1467 1546 renameTypes( alternatives.back().expr ); 1468 1547 } // for … … 1479 1558 for ( const Alternative & first : firstFinder.alternatives ) { 1480 1559 for ( const Alternative & second : secondFinder.alternatives ) { 1481 TypeEnvironment compositeEnv{ first.env }; 1560 TypeEnvironment compositeEnv; 1561 compositeEnv.simpleCombine( first.env ); 1482 1562 compositeEnv.simpleCombine( second.env ); 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 } ); 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 ) ); 1494 1566 } 1495 1567 } … … 1512 1584 for ( const Alternative & second : secondFinder.alternatives ) { 1513 1585 for ( const Alternative & third : thirdFinder.alternatives ) { 1514 TypeEnvironment compositeEnv{ first.env }; 1586 TypeEnvironment compositeEnv; 1587 compositeEnv.simpleCombine( first.env ); 1515 1588 compositeEnv.simpleCombine( second.env ); 1516 1589 compositeEnv.simpleCombine( third.env ); 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 1590 1526 1591 // 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 ); 1527 1595 Type* commonType = nullptr; 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() }; 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() ); 1532 1598 newExpr->result = commonType ? commonType : second.expr->result->clone(); 1533 1599 // convert both options to the conditional result type 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 ) ); 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 ) ); 1544 1604 } // if 1545 1605 } // for … … 1554 1614 secondFinder.findWithAdjustment( commaExpr->get_arg2() ); 1555 1615 for ( const Alternative & alt : secondFinder.alternatives ) { 1556 alternatives.push_back( Alternative{ 1557 alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } ); 1616 alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) ); 1558 1617 } // for 1559 1618 delete newFirstArg; … … 1570 1629 for ( const Alternative & first : firstFinder.alternatives ) { 1571 1630 for ( const Alternative & second : secondFinder.alternatives ) { 1572 TypeEnvironment compositeEnv{ first.env }; 1631 TypeEnvironment compositeEnv; 1632 compositeEnv.simpleCombine( first.env ); 1573 1633 compositeEnv.simpleCombine( second.env ); 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 1634 OpenVarSet openVars; 1635 AssertionSet needAssertions, haveAssertions; 1636 Alternative newAlt( 0, compositeEnv, first.cost + second.cost ); 1581 1637 Type* commonType = nullptr; 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() }; 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() ); 1586 1640 newExpr->result = commonType ? commonType : first.expr->result->clone(); 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 ) ); 1641 newAlt.expr = newExpr; 1642 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); 1591 1643 } // if 1592 1644 } // for … … 1606 1658 1607 1659 TypeEnvironment compositeEnv; 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 ) } ); 1660 simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv ); 1661 alternatives.push_back( 1662 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } ); 1619 1663 } // for 1620 1664 } 1621 1665 1622 1666 void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) { 1623 alternatives.push_back( Alternative { tupleExpr->clone(), env });1667 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1624 1668 } 1625 1669 1626 1670 void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) { 1627 alternatives.push_back( Alternative { impCpCtorExpr->clone(), env });1671 alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) ); 1628 1672 } 1629 1673 … … 1634 1678 finder.findWithoutPrune( ctorExpr->get_callExpr() ); 1635 1679 for ( Alternative & alt : finder.alternatives ) { 1636 alternatives.push_back( Alternative{ 1637 alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } ); 1680 alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) ); 1638 1681 } 1639 1682 } 1640 1683 1641 1684 void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) { 1642 alternatives.push_back( Alternative { tupleExpr->clone(), env });1685 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1643 1686 } 1644 1687 1645 1688 void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) { 1646 alternatives.push_back( Alternative { tupleAssignExpr->clone(), env });1689 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) ); 1647 1690 } 1648 1691 … … 1653 1696 // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked" 1654 1697 UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() ); 1655 alternatives.push_back( Alternative { alt, newUnqExpr, alt.cost });1698 alternatives.push_back( Alternative( newUnqExpr, alt.env, alt.cost ) ); 1656 1699 } 1657 1700 } … … 1661 1704 ResolvExpr::resolveStmtExpr( newStmtExpr, indexer ); 1662 1705 // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr... 1663 alternatives.push_back( Alternative { newStmtExpr, env });1706 alternatives.push_back( Alternative( newStmtExpr, env, Cost::zero ) ); 1664 1707 } 1665 1708 … … 1683 1726 for ( Alternative & alt : finder.get_alternatives() ) { 1684 1727 TypeEnvironment newEnv( alt.env ); 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? 1728 AssertionSet needAssertions, haveAssertions; 1729 OpenVarSet openVars; // find things in env that don't have a "representative type" and claim those are open vars? 1691 1730 PRINT( 1692 1731 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1693 1732 ) 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. 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. 1699 1737 int discardedValues = alt.expr->result->size() - toType->size(); 1700 1738 if ( discardedValues < 0 ) continue; 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 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])) 1705 1741 // unification run for side-effects 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? 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?? 1708 1743 1709 1744 Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv ); … … 1711 1746 // count one safe conversion for each value that is thrown away 1712 1747 thisCost.incSafe( discardedValues ); 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 ) ); 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 ) ); 1719 1750 } 1720 1751 } -
src/ResolvExpr/AlternativeFinder.h
r276a55b2 r07ec1a2 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sat May 16 23:56:12 2015 11 // Last Modified By : A aron B. Moss12 // Last Modified On : Fri Oct -5 10:01:00 201813 // Update Count : 511 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Jul 26 11:24:00 2017 13 // Update Count : 4 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 ResolvMode27 26 #include "SynTree/Visitor.h" // for Visitor 28 27 #include "SynTree/SynTree.h" // for Visitor Nodes … … 69 68 } 70 69 71 void find( Expression *expr, ResolvMode mode = ResolvMode{});70 void find( Expression *expr, bool adjust = false, bool prune = true, bool failFast = true ); 72 71 /// Calls find with the adjust flag set; adjustment turns array and function types into equivalent pointer types 73 72 void findWithAdjustment( Expression *expr ); -
src/ResolvExpr/ConversionCost.cc
r276a55b2 r07ec1a2 28 28 29 29 namespace ResolvExpr { 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 }; 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 ); 38 36 39 37 #if 0 -
src/ResolvExpr/Cost.h
r276a55b2 r07ec1a2 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 09:39:50 2015 11 // Last Modified By : Aaron B. Moss12 // Last Modified On : Fri Oct 05 14:32:00 201813 // Update Count : 711 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 22 09:35:55 2017 13 // Update Count : 5 14 14 // 15 15 … … 21 21 class Cost { 22 22 private: 23 Cost( int unsafeCost, int polyCost, int safeCost, int varCost, int specCost, 24 int referenceCost ); 23 Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ); 25 24 26 25 public: … … 28 27 Cost & incPoly( int inc = 1 ); 29 28 Cost & incSafe( int inc = 1 ); 30 Cost & incVar( int inc = 1 );31 Cost & decSpec( int inc = 1 );32 29 Cost & incReference( int inc = 1 ); 33 30 … … 35 32 int get_polyCost() const { return polyCost; } 36 33 int get_safeCost() const { return safeCost; } 37 int get_varCost() const { return varCost; }38 int get_specCost() const { return specCost; }39 34 int get_referenceCost() const { return referenceCost; } 40 35 … … 46 41 bool operator!=( const Cost &other ) const; 47 42 friend std::ostream &operator<<( std::ostream &os, const Cost &cost ); 48 // returns negative for *this < other, 0 for *this == other, positive for *this > other49 int compare( const Cost &other ) const;50 43 51 44 static const Cost zero; … … 55 48 static const Cost poly; 56 49 static const Cost safe; 57 static const Cost var;58 static const Cost spec;59 50 static const Cost reference; 51 private: 52 int compare( const Cost &other ) const; 60 53 61 private: 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 54 int unsafeCost; 55 int polyCost; 56 int safeCost; 57 int referenceCost; 68 58 }; 69 59 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 ) {} 60 inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ) : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), referenceCost( referenceCost ) {} 74 61 75 62 inline Cost & Cost::incUnsafe( int inc ) { … … 91 78 } 92 79 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;102 return *this;103 }104 105 80 inline Cost & Cost::incReference( int inc ) { 106 81 if ( *this == infinity ) return *this; … … 111 86 inline Cost Cost::operator+( const Cost &other ) const { 112 87 if ( *this == infinity || other == infinity ) return infinity; 113 return Cost{ 114 unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost, 115 varCost + other.varCost, specCost + other.specCost, 116 referenceCost + other.referenceCost }; 88 return Cost( unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost, referenceCost + other.referenceCost ); 117 89 } 118 90 119 91 inline Cost Cost::operator-( const Cost &other ) const { 120 92 if ( *this == infinity || other == infinity ) return infinity; 121 return Cost{ 122 unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost, 123 varCost - other.varCost, specCost - other.specCost, 124 referenceCost - other.referenceCost }; 93 return Cost( unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost, referenceCost - other.referenceCost ); 125 94 } 126 95 … … 134 103 polyCost += other.polyCost; 135 104 safeCost += other.safeCost; 136 varCost += other.varCost;137 specCost += other.specCost;138 105 referenceCost += other.referenceCost; 139 106 return *this; … … 156 123 } else if ( safeCost < other.safeCost ) { 157 124 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;166 125 } else if ( referenceCost > other.referenceCost ) { 167 126 return false; … … 173 132 } 174 133 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;185 }186 187 134 inline bool Cost::operator==( const Cost &other ) const { 188 135 return unsafeCost == other.unsafeCost 189 136 && polyCost == other.polyCost 190 137 && safeCost == other.safeCost 191 && varCost == other.varCost192 && specCost == other.specCost193 138 && referenceCost == other.referenceCost; 194 139 } … … 199 144 200 145 inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) { 201 return os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " 202 << cost.safeCost << ", " << cost.varCost << ", " << cost.specCost << ", " 203 << cost.referenceCost << " )"; 146 os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " << cost.safeCost << ", " << cost.referenceCost << " )"; 147 return os; 204 148 } 205 149 } // namespace ResolvExpr -
src/ResolvExpr/Resolver.cc
r276a55b2 r07ec1a2 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:17:01 2015 11 // Last Modified By : Aaron B. Moss12 // Last Modified On : Fri Oct 05 09:43:00 201813 // Update Count : 21 411 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 17 11:19:40 2018 13 // Update Count : 213 14 14 // 15 15 16 #include <stddef.h> // for NULL 16 17 #include <cassert> // for strict_dynamic_cast, assert 17 18 #include <memory> // for allocator, allocator_traits<... 18 19 #include <tuple> // for get 19 #include <vector> // for vector20 #include <vector> 20 21 21 22 #include "Alternative.h" // for Alternative, AltList … … 30 31 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 31 32 #include "Resolver.h" 32 #include "ResolvMode.h" // for ResolvMode33 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, ResolvMode mode = ResolvMode{}) {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) { 171 171 assertf( untyped, "expected a non-null expression." ); 172 173 // xxx - this isn't thread-safe, but should work until we parallelize the resolver174 static unsigned recursion_level = 0;175 176 ++recursion_level;177 172 TypeEnvironment env; 178 173 AlternativeFinder finder( indexer, env ); 179 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 180 --recursion_level; 174 finder.find( untyped, adjust, prune, failFast ); 181 175 182 176 #if 0 … … 191 185 #endif 192 186 193 // produce filtered list of alternatives194 187 AltList candidates; 195 188 for ( Alternative & alt : finder.get_alternatives() ) { … … 199 192 } 200 193 201 // produce invalid error if no candidates 202 if ( candidates.empty() ) { 194 // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining 195 // choose the lowest cost expression among the candidates 196 AltList winners; 197 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 198 if ( winners.size() == 0 ) { 203 199 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") ); 204 } 205 206 // search for cheapest candidate 207 AltList winners; 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 ) { 200 } else if ( winners.size() != 1 ) { 240 201 std::ostringstream stream; 241 202 stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n"; … … 246 207 } 247 208 248 // single selected choice 249 Alternative& choice = winners.front(); 250 251 // fail on only expression deleted 252 if ( ! seen_undeleted ) { 209 // there is one unambiguous interpretation - move the expression into the with statement 210 Alternative & choice = winners.front(); 211 if ( findDeletedExpr( choice.expr ) ) { 253 212 SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " ); 254 213 } 255 256 // xxx - check for ambiguous expressions257 258 // output selected choice259 214 alt = std::move( choice ); 260 215 } 261 216 262 217 /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages 263 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {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) { 264 219 if ( ! untyped ) return; 265 220 Alternative choice; 266 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode);221 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast ); 267 222 finishExpr( choice.expr, choice.env, untyped->env ); 268 223 delete untyped; … … 295 250 untyped.arg = expr; 296 251 Alternative choice; 297 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment());252 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true ); 298 253 CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr ); 299 254 env = std::move( choice.env ); … … 402 357 403 358 void Resolver::previsit( ObjectDecl *objectDecl ) { 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 object407 // declarations in the return and parameter types. So each value of initContext is408 // retained, so the type on the first analysis is preserved and used for selectingthe RHS.359 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable 360 // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes 361 // initContext because of a function type can contain object declarations in the return and parameter types. So 362 // each value of initContext is retained, so the type on the first analysis is preserved and used for selecting 363 // the RHS. 409 364 GuardValue( currentObject ); 410 365 currentObject = CurrentObject( objectDecl->get_type() ); … … 442 397 443 398 void Resolver::postvisit( FunctionDecl *functionDecl ) { 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. 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. 448 402 for ( Declaration * d : functionDecl->type->parameters ) { 449 403 if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) { … … 795 749 initExpr->expr = nullptr; 796 750 std::swap( initExpr->env, newExpr->env ); 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. 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. 800 753 newExpr->spliceInferParams( initExpr ); 801 754 delete initExpr; 802 755 803 // get the actual object's type (may not exactly match what comes back from the resolver 804 // due to conversions) 756 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions) 805 757 Type * initContext = currentObject.getCurrentType(); 806 758 … … 814 766 if ( isCharType( pt->get_base() ) ) { 815 767 if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) { 816 // strip cast if we're initializing a char[] with a char *, 817 // e.g. char x[] = "hello"; 768 // strip cast if we're initializing a char[] with a char *, e.g. char x[] = "hello"; 818 769 newExpr = ce->get_arg(); 819 770 ce->set_arg( nullptr ); … … 837 788 // move cursor into brace-enclosed initializer-list 838 789 currentObject.enterListInit(); 839 // xxx - fix this so that the list isn't copied, iterator should be used to change current 840 // element 790 // xxx - fix this so that the list isn't copied, iterator should be used to change current element 841 791 std::list<Designation *> newDesignations; 842 792 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) { 843 // iterate designations and initializers in pairs, moving the cursor to the current 844 // designated object and resolvingthe initializer against that object.793 // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving 794 // the initializer against that object. 845 795 Designation * des = std::get<0>(p); 846 796 Initializer * init = std::get<1>(p); … … 872 822 // fall back on C-style initializer 873 823 delete ctorInit->get_ctor(); 874 ctorInit->set_ctor( nullptr);824 ctorInit->set_ctor( NULL ); 875 825 delete ctorInit->get_dtor(); 876 ctorInit->set_dtor( nullptr);826 ctorInit->set_dtor( NULL ); 877 827 maybeAccept( ctorInit->get_init(), *visitor ); 878 828 } … … 917 867 918 868 // xxx - todo -- what about arrays? 919 // if ( dtor == nullptr&& InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {869 // if ( dtor == NULL && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) { 920 870 // // can reduce the constructor down to a SingleInit using the 921 871 // // second argument from the ctor call, since 922 872 // delete ctorInit->get_ctor(); 923 // ctorInit->set_ctor( nullptr);873 // ctorInit->set_ctor( NULL ); 924 874 925 875 // Expression * arg = -
src/ResolvExpr/TypeEnvironment.cc
r276a55b2 r07ec1a2 120 120 121 121 const EqvClass* TypeEnvironment::lookup( const std::string &var ) const { 122 for ( ClassList::const_iterator i = env.begin(); i != env.end(); ++i ) {122 for ( std::list< EqvClass >::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 ( ClassList::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {170 for ( std::list< EqvClass >::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 TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const std::string &var ) {191 for ( ClassList::iterator i = env.begin(); i != env.end(); ++i ) {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 ) { 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 types206 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 necessary212 if ( common ) {213 common->get_qualifiers() = Type::Qualifiers{};214 to.set_type( common );215 }216 } else return false; // cannot unify217 } else {218 to.type = from.type->clone();219 }220 }221 222 // unify widening if matches223 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 match233 if ( ! mergeBound( r, s, openVars, indexer ) ) return false;234 235 // check safely bindable236 if ( r.type && occursIn( r.type, s.vars.begin(), s.vars.end(), *this ) ) return false;237 238 // merge classes in239 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 cases248 if ( o.isEmpty() ) return true;249 if ( isEmpty() ) {250 simpleCombine( o );251 return true;252 }253 254 // merge classes255 for ( auto ct = o.env.begin(); ct != o.env.end(); ++ct ) {256 const EqvClass& c = *ct;257 258 // typeclass in local environment bound to c259 auto rt = env.end();260 261 // look for first existing bound variable262 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 *rt269 EqvClass& r = *rt;270 // merge bindings271 if ( ! mergeBound( r, c, openVars, indexer ) ) return false;272 // merge previous unbound variables into this class, checking occurs if needed273 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 occurs282 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 class286 if ( ! mergeClasses( rt, st, openVars, indexer ) ) return false;287 } // ignore bound into the same class288 }289 } else { // no variables in c bound; just copy up290 env.push_back( c );291 }292 }293 294 // merged all classes295 return true;296 }297 298 201 void TypeEnvironment::extractOpenVars( OpenVarSet &openVars ) const { 299 for ( ClassList::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) {202 for ( std::list< EqvClass >::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) { 300 203 for ( std::set< std::string >::const_iterator var = eqvClass->vars.begin(); var != eqvClass->vars.end(); ++var ) { 301 204 openVars[ *var ] = eqvClass->data; -
src/ResolvExpr/TypeEnvironment.h
r276a55b2 r07ec1a2 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 42 // comparator. 41 // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator. 43 42 // 44 43 // Note: since this compares pointers for position, minor changes in the source file that affect 45 44 // memory layout can alter compilation time in unpredictable ways. For example, the placement 46 45 // of a line directive can reorder type pointers with respect to each other so that assertions 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. 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. 53 51 struct AssertCompare { 54 52 bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const { … … 59 57 }; 60 58 struct AssertionSetValue { 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) {} 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; 65 64 }; 66 65 typedef std::map< DeclarationWithType*, AssertionSetValue, AssertCompare > AssertionSet; 67 66 typedef std::map< std::string, TypeDecl::Data > OpenVarSet; 68 69 /// merges one set of open vars into another70 static inline void mergeOpenVars( OpenVarSet& dst, const OpenVarSet& src ) {71 for ( const auto& entry : src ) { dst[ entry.first ] = entry.second; }72 }73 67 74 68 void printAssertionSet( const AssertionSet &, std::ostream &, int indent = 0 ); … … 97 91 98 92 class TypeEnvironment { 99 using ClassList = std::list< EqvClass >;100 93 public: 101 94 const EqvClass* lookup( const std::string &var ) const; … … 110 103 bool isEmpty() const { return env.empty(); } 111 104 void print( std::ostream &os, Indenter indent = {} ) const; 112 113 /// Simply concatenate the second environment onto this one; no safety checks performed 105 // void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) ); 114 106 void simpleCombine( const TypeEnvironment &second ); 115 116 private:117 /// Unifies the type bound of to with the type bound of from, returning false if fails118 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 fails121 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 128 107 void extractOpenVars( OpenVarSet &openVars ) const; 129 108 TypeEnvironment *clone() const { return new TypeEnvironment( *this ); } … … 144 123 void forbidWidening(); 145 124 146 using iterator = ClassList::const_iterator;125 using iterator = std::list< EqvClass >::const_iterator; 147 126 iterator begin() const { return env.begin(); } 148 127 iterator end() const { return env.end(); } 149 128 150 129 private: 151 ClassListenv;130 std::list< EqvClass > env; 152 131 153 ClassList::iterator internal_lookup( const std::string &var );132 std::list< EqvClass >::iterator internal_lookup( const std::string &var ); 154 133 }; 155 134 -
src/ResolvExpr/module.mk
r276a55b2 r07ec1a2 33 33 ResolvExpr/TypeEnvironment.cc \ 34 34 ResolvExpr/CurrentObject.cc \ 35 ResolvExpr/ExplodedActual.cc \ 36 ResolvExpr/SpecCost.cc \ 37 ResolvExpr/ResolveAssertions.cc 35 ResolvExpr/ExplodedActual.cc -
src/ResolvExpr/typeops.h
r276a55b2 r07ec1a2 72 72 Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ); 73 73 74 // in AlternativeFinder.cc75 Cost computeConversionCost( Type *actualType, Type *formalType,76 const SymTab::Indexer &indexer, const TypeEnvironment &env );77 78 74 // in PtrsAssignable.cc 79 75 int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env ); … … 106 102 int polyCost( Type *type, const TypeEnvironment &env, const SymTab::Indexer &indexer ); 107 103 108 // in SpecCost.cc109 int specCost( Type *type );110 111 104 // in Occurs.cc 112 105 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 }122 106 123 107 // in AlternativeFinder.cc -
src/SynTree/ApplicationExpr.cc
r276a55b2 r07ec1a2 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
r276a55b2 r07ec1a2 40 40 Declaration::declFromId( i->second.decl )->printShort( os, indent+1 ); 41 41 os << std::endl; 42 printInferParams( i->second.expr->inferParams, os, indent+1, level+1 );42 printInferParams( *i->second.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 ), resnSlots( other.resnSlots ) {} 49 Expression::Expression( const Expression &other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), extension( other.extension ), inferParams( other.inferParams ) { 50 } 50 51 51 52 void Expression::spliceInferParams( Expression * other ) { … … 54 55 inferParams[p.first] = std::move( p.second ); 55 56 } 56 resnSlots.insert( resnSlots.end(), other->resnSlots.begin(), other->resnSlots.end() );57 57 } 58 58 -
src/SynTree/Expression.h
r276a55b2 r07ec1a2 21 21 #include <memory> // for allocator, unique_ptr 22 22 #include <string> // for string 23 #include <vector> // for vector24 23 25 24 #include "BaseSyntaxNode.h" // for BaseSyntaxNode … … 39 38 /// but subject to decay-to-pointer and type parameter renaming 40 39 struct ParamEntry { 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 )*/{}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 ) {} 43 42 ParamEntry( const ParamEntry & other ); 44 43 ParamEntry( ParamEntry && other ); … … 51 50 Type * formalType; 52 51 Expression * expr; 53 //std::unique_ptr< InferredParams > inferParams;52 std::unique_ptr< InferredParams > inferParams; 54 53 }; 55 54 … … 60 59 TypeSubstitution * env; 61 60 bool extension = false; 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 61 InferredParams inferParams; 66 62 67 63 Expression(); … … 77 73 bool get_extension() const { return extension; } 78 74 Expression * set_extension( bool exten ) { extension = exten; return this; } 75 76 InferredParams & get_inferParams() { return inferParams; } 79 77 80 78 // move other's inferParams to this -
src/Tuples/Explode.h
r276a55b2 r07ec1a2 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,47 46 const ResolvExpr::Cost& cost, const ResolvExpr::Cost& cvtCost ) { 48 *out++ = ResolvExpr::Alternative{ expr, env, openVars, need,cost, cvtCost };47 *out++ = ResolvExpr::Alternative{ expr, env, cost, cvtCost }; 49 48 } 50 49 51 50 /// Append alternative to an ExplodedActual 52 51 static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr, 53 const ResolvExpr::TypeEnvironment&, const ResolvExpr::OpenVarSet&, 54 const ResolvExpr::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) { 52 const ResolvExpr::TypeEnvironment&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) { 55 53 ea.exprs.emplace_back( expr ); 56 /// xxx -- merge environment, openVars, need,cost?54 /// xxx -- merge environment, cost? 57 55 } 58 56 … … 70 68 // distribute reference cast over all components 71 69 append( std::forward<Output>(out), distributeReference( alt.release_expr() ), 72 alt.env, alt. openVars, alt.need, alt.cost, alt.cvtCost );70 alt.env, alt.cost, alt.cvtCost ); 73 71 } 74 72 // 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) … … 104 102 } else { 105 103 // atomic (non-tuple) type - output a clone of the expression in a new alternative 106 append( std::forward<Output>(out), expr->clone(), alt.env, alt.openVars, alt.need, 107 alt.cost, alt.cvtCost ); 104 append( std::forward<Output>(out), expr->clone(), alt.env, alt.cost, alt.cvtCost ); 108 105 } 109 106 } -
src/Tuples/TupleAssignment.cc
r276a55b2 r07ec1a2 62 62 struct Matcher { 63 63 public: 64 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, 65 constResolvExpr::AltList& rhs );64 Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const 65 ResolvExpr::AltList& rhs ); 66 66 virtual ~Matcher() {} 67 68 67 virtual void match( std::list< Expression * > &out ) = 0; 69 68 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 81 69 ResolvExpr::AltList lhs, rhs; 82 70 TupleAssignSpotter &spotter; … … 84 72 std::list< ObjectDecl * > tmpDecls; 85 73 ResolvExpr::TypeEnvironment compositeEnv; 86 ResolvExpr::OpenVarSet openVars;87 ResolvExpr::AssertionSet need;88 74 }; 89 75 … … 259 245 } 260 246 261 // extract expressions from the assignment alternatives to produce a list of assignments 262 // t hat together form a single alternative247 // extract expressions from the assignment alternatives to produce a list of assignments that 248 // together form a single alternative 263 249 std::list< Expression *> solved_assigns; 264 250 for ( ResolvExpr::Alternative & alt : current ) { 265 251 solved_assigns.push_back( alt.expr->clone() ); 266 matcher->combineState( alt );267 }268 252 } 253 // combine assignment environments into combined expression environment 254 simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv ); 269 255 // xxx -- was push_front 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 } ); 256 currentFinder.get_alternatives().push_back( ResolvExpr::Alternative( 257 new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv, 258 ResolvExpr::sumCost( current ) + matcher->baseCost ) ); 275 259 } 276 260 … … 279 263 : lhs(lhs), rhs(rhs), spotter(spotter), 280 264 baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) { 281 combineState( lhs );282 combineState( rhs);265 simpleCombineEnvironments( lhs.begin(), lhs.end(), compositeEnv ); 266 simpleCombineEnvironments( rhs.begin(), rhs.end(), compositeEnv ); 283 267 } 284 268 -
tests/.expect/castError.txt
r276a55b2 r07ec1a2 4 4 ... to: 5 5 char Alternatives are: 6 Cost ( 1, 0, 0, 0 , 0, 0): Cast of:6 Cost ( 1, 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 , 0, 0): Cast of:18 Cost ( 1, 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 , 0, 0): Cast of:27 Cost ( 1, 0, 0, 0 ): Cast of: 28 28 Variable Expression: f: signed int 29 29 ... to: -
tests/searchsort.cfa
r276a55b2 r07ec1a2 57 57 58 58 // descending sort/search by changing < to > 59 for ( i; 0 ~ size ) {59 for ( i; 0u ~ size ) { 60 60 iarr[i] = i + 1; 61 61 sout | iarr[i] | ", ";
Note:
See TracChangeset
for help on using the changeset viewer.