Changes in / [276a55b2:07ec1a2]


Ignore:
Files:
5 deleted
23 edited

Legend:

Unmodified
Added
Removed
  • src/Common/utility.h

    r276a55b2 r07ec1a2  
    2626#include <string>
    2727#include <type_traits>
    28 #include <utility>
    2928
    3029#include <cassert>
     
    463462std::pair<long long int, bool> eval(Expression * expr);
    464463
    465 // -----------------------------------------------------------------------------
    466 /// Reorders the input range in-place so that the minimal-value elements according to the
    467 /// comparator are in front;
    468 /// returns the iterator after the last minimal-value element.
    469 template<typename Iter, typename Compare>
    470 Iter sort_mins( Iter begin, Iter end, Compare& lt ) {
    471         if ( begin == end ) return end;
    472        
    473         Iter min_pos = begin;
    474         for ( Iter i = begin + 1; i != end; ++i ) {
    475                 if ( lt( *i, *min_pos ) ) {
    476                         // new minimum cost; swap into first position
    477                         min_pos = begin;
    478                         std::iter_swap( min_pos, i );
    479                 } else if ( ! lt( *min_pos, *i ) ) {
    480                         // duplicate minimum cost; swap into next minimum position
    481                         ++min_pos;
    482                         std::iter_swap( min_pos, i );
    483                 }
    484         }
    485         return ++min_pos;
    486 }
    487 
    488 template<typename Iter, typename Compare>
    489 inline Iter sort_mins( Iter begin, Iter end, Compare&& lt ) {
    490         return sort_mins( begin, end, lt );
    491 }
    492 
    493 /// sort_mins defaulted to use std::less
    494 template<typename Iter>
    495 inline Iter sort_mins( Iter begin, Iter end ) {
    496         return sort_mins( begin, end, std::less<typename std::iterator_traits<Iter>::value_type>{} );
    497 }
    498 
    499464// Local Variables: //
    500465// tab-width: 4 //
  • src/GenPoly/Box.cc

    r276a55b2 r07ec1a2  
    798798                        for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
    799799                                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() );
    802802                                        Expression *newExpr = inferParam->second.expr->clone();
    803803                                        addCast( newExpr, (*assert)->get_type(), tyVars );
  • src/GenPoly/Specialize.cc

    r276a55b2 r07ec1a2  
    245245                appExpr->env = TypeSubstitution::newFromExpr( appExpr, env );
    246246                if ( inferParams ) {
    247                         appExpr->inferParams = *inferParams;
     247                        appExpr->get_inferParams() = *inferParams;
    248248                } // if
    249249
     
    284284                std::list< Expression* >::iterator actual;
    285285                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() );
    287287                }
    288288        }
     
    295295                        // alternatively, if order starts to matter then copy appExpr's inferParams and pass them to handleExplicitParams.
    296296                        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() );
    299299                        }
    300300                }
  • src/Makefile.am

    r276a55b2 r07ec1a2  
    127127  ResolvExpr/PtrsCastable.cc \
    128128  ResolvExpr/RenameVars.cc \
    129   ResolvExpr/ResolveAssertions.cc \
    130129  ResolvExpr/Resolver.cc \
    131130  ResolvExpr/ResolveTypeof.cc \
    132   ResolvExpr/SpecCost.cc \
    133131  ResolvExpr/TypeEnvironment.cc \
    134132  ResolvExpr/Unify.cc \
  • src/Makefile.in

    r276a55b2 r07ec1a2  
    206206        ResolvExpr/PtrsAssignable.$(OBJEXT) \
    207207        ResolvExpr/PtrsCastable.$(OBJEXT) \
    208         ResolvExpr/RenameVars.$(OBJEXT) \
    209         ResolvExpr/ResolveAssertions.$(OBJEXT) \
    210         ResolvExpr/Resolver.$(OBJEXT) \
     208        ResolvExpr/RenameVars.$(OBJEXT) ResolvExpr/Resolver.$(OBJEXT) \
    211209        ResolvExpr/ResolveTypeof.$(OBJEXT) \
    212         ResolvExpr/SpecCost.$(OBJEXT) \
    213210        ResolvExpr/TypeEnvironment.$(OBJEXT) \
    214211        ResolvExpr/Unify.$(OBJEXT) SymTab/Autogen.$(OBJEXT) \
     
    265262        ResolvExpr/TypeEnvironment.$(OBJEXT) \
    266263        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) \
    277271        SynTree/ReferenceToType.$(OBJEXT) SynTree/TupleType.$(OBJEXT) \
    278272        SynTree/TypeofType.$(OBJEXT) SynTree/AttrType.$(OBJEXT) \
     
    595589        ResolvExpr/Occurs.cc ResolvExpr/TypeEnvironment.cc \
    596590        ResolvExpr/CurrentObject.cc ResolvExpr/ExplodedActual.cc \
    597         ResolvExpr/SpecCost.cc ResolvExpr/ResolveAssertions.cc \
    598591        SymTab/Indexer.cc SymTab/Mangler.cc SymTab/ManglerCommon.cc \
    599592        SymTab/Validate.cc SymTab/FixFunction.cc SymTab/Autogen.cc \
     
    703696  ResolvExpr/PtrsCastable.cc \
    704697  ResolvExpr/RenameVars.cc \
    705   ResolvExpr/ResolveAssertions.cc \
    706698  ResolvExpr/Resolver.cc \
    707699  ResolvExpr/ResolveTypeof.cc \
    708   ResolvExpr/SpecCost.cc \
    709700  ResolvExpr/TypeEnvironment.cc \
    710701  ResolvExpr/Unify.cc \
     
    955946ResolvExpr/RenameVars.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    956947        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    957 ResolvExpr/ResolveAssertions.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    958         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    959948ResolvExpr/Resolver.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    960949        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    961950ResolvExpr/ResolveTypeof.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    962         ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    963 ResolvExpr/SpecCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    964951        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    965952ResolvExpr/TypeEnvironment.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     
    12201207@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/PtrsCastable.Po@am__quote@
    12211208@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@
    12231209@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ResolveTypeof.Po@am__quote@
    12241210@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@
    12261211@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/TypeEnvironment.Po@am__quote@
    12271212@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Unify.Po@am__quote@
  • src/ResolvExpr/Alternative.cc

    r276a55b2 r07ec1a2  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:44:23 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Thu Oct 11 10:55:00 2018
    13 // Update Count     : 3
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat May 16 23:54:23 2015
     13// Update Count     : 2
    1414//
    1515
     
    2020#include <utility>                       // for move
    2121
    22 #include "Common/utility.h"              // for cloneAll
     22#include "Common/utility.h"              // for maybeClone
    2323#include "ResolvExpr/Cost.h"             // for Cost, Cost::zero, operator<<
    2424#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
     
    2727
    2828namespace 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 ) {}
    3130
    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 ) {}
    3833
    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 ) {}
    4336
    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        }
    7439
    7540        Alternative &Alternative::operator=( const Alternative &other ) {
     
    8045                expr = maybeClone( other.expr );
    8146                env = other.env;
    82                 openVars = other.openVars;
    83                 need.clear();
    84                 cloneAll( other.need, need );
    8547                return *this;
    8648        }
    8749
    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        }
    9253
    9354        Alternative & Alternative::operator=( Alternative && other ) {
     
    9859                expr = other.expr;
    9960                env = std::move( other.env );
    100                 openVars = std::move( other.openVars );
    101                 need = std::move( other.need );
    10261                other.expr = nullptr;
    10362                return *this;
     
    10564
    10665        Alternative::~Alternative() {
    107                 for ( AssertionItem& n : need ) { delete n.decl; }
    10866                delete expr;
    10967        }
  • src/ResolvExpr/Alternative.h

    r276a55b2 r07ec1a2  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:45:43 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Thu Oct 11 10:55:00 2018
    13 // Update Count     : 4
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:36:36 2017
     13// Update Count     : 3
    1414//
    1515
     
    2020
    2121#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
    2523
    2624class Expression;
    2725
    2826namespace ResolvExpr {
    29         /// One assertion to resolve
    30         struct AssertionItem {
    31                 DeclarationWithType* decl;
    32                 AssertionSetValue info;
    33                
    34                 AssertionItem() = default;
    35                 AssertionItem( DeclarationWithType* decl, const AssertionSetValue& info )
    36                 : decl(decl), info(info) {}
    37                 AssertionItem( const AssertionSet::value_type& e ) : decl(e.first), info(e.second) {}
    38                 operator AssertionSet::value_type () const { return { decl, info }; }
    39 
    40                 // to support cloneAll
    41                 AssertionItem clone() const { return { maybeClone(decl), info }; }
    42         };
    43         /// A list of unresolved assertions
    44         using AssertionList = std::vector<AssertionItem>;
    45 
    46         /// Clones an assertion list into an assertion set
    47         static inline void cloneAll( const AssertionList& src, AssertionSet& dst ) {
    48                 for ( const AssertionItem& item : src ) {
    49                         dst.emplace( maybeClone(item.decl), item.info );
    50                 }
    51         }
    52 
    53         /// Clones an assertion set into an assertion list
    54         static inline void cloneAll( const AssertionSet& src, AssertionList& dst ) {
    55                 dst.reserve( dst.size() + src.size() );
    56                 for ( const auto& entry : src ) {
    57                         dst.emplace_back( maybeClone(entry.first), entry.second );
    58                 }
    59         }
    60 
    61         /// Clones an assertion list into an assertion list
    62         static inline void cloneAll( const AssertionList& src, AssertionList& dst ) {
    63                 dst.reserve( dst.size() + src.size() );
    64                 for ( const AssertionItem& item : src ) {
    65                         dst.emplace_back( maybeClone(item.decl), item.info );
    66                 }
    67         }
    68 
    69         /// One option for resolution of an expression
    7027        struct Alternative {
    7128                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 );
    8631                Alternative( const Alternative &other );
    8732                Alternative &operator=( const Alternative &other );
     
    9944                }
    10045
    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;
    11050        };
    11151
  • src/ResolvExpr/AlternativeFinder.cc

    r276a55b2 r07ec1a2  
    1111// Last Modified By : Peter A. Buhr
    1212// Last Modified On : Thu Nov  1 21:00:56 2018
    13 // Update Count     : 35
     13// Update Count     : 34
    1414//
    1515
     
    3434#include "InitTweak/InitTweak.h"   // for getFunctionName
    3535#include "RenameVars.h"            // for RenameVars, global_renamer
    36 #include "ResolveAssertions.h"     // for resolveAssertions
    3736#include "ResolveTypeof.h"         // for resolveTypeof
    3837#include "Resolver.h"              // for resolveStmtExpr
     
    103102                void addAnonConversions( const Alternative & alt );
    104103                /// 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 );
    106105                /// 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 );
    108107                /// Adds alternatives for offsetof expressions, given the base type and name of the member
    109108                template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
     
    114113                template<typename OutputIterator>
    115114                void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out );
    116                 /// Sets up parameter inference for an output alternative
     115                /// Checks if assertion parameters match for a new alternative
    117116                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 );
    119118        private:
    120119                AlternativeFinder & altFinder;
     
    245244        }
    246245
    247         void AlternativeFinder::find( Expression *expr, ResolvMode mode ) {
     246        void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) {
    248247                PassVisitor<Finder> finder( *this );
    249248                expr->accept( finder );
    250                 if ( mode.failFast && alternatives.empty() ) {
     249                if ( failFast && alternatives.empty() ) {
    251250                        PRINT(
    252251                                std::cerr << "No reasonable alternatives for expression " << expr << std::endl;
     
    254253                        SemanticError( expr, "No reasonable alternatives for expression " );
    255254                }
    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 ) {
    275256                        auto oldsize = alternatives.size();
    276257                        PRINT(
     
    280261                        AltList pruned;
    281262                        pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) );
    282                         if ( mode.failFast && pruned.empty() ) {
     263                        if ( failFast && pruned.empty() ) {
    283264                                std::ostringstream stream;
    284265                                AltList winners;
     
    299280                }
    300281                // 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 );
    304285                        }
    305286                }
     
    313294
    314295        void AlternativeFinder::findWithAdjustment( Expression *expr ) {
    315                 find( expr, ResolvMode::withAdjustment() );
     296                find( expr, true );
    316297        }
    317298
    318299        void AlternativeFinder::findWithoutPrune( Expression * expr ) {
    319                 find( expr, ResolvMode::withoutPrune() );
     300                find( expr, true, false );
    320301        }
    321302
    322303        void AlternativeFinder::maybeFind( Expression * expr ) {
    323                 find( expr, ResolvMode::withoutFailFast() );
     304                find( expr, true, true, false );
    324305        }
    325306
     
    336317
    337318                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, "" );
    339320                } 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, "" );
    341322                } // if
    342323        }
    343324
    344325        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 ) {
    346327                std::list< Declaration* > members;
    347328                aggInst->lookup( name, members );
     
    351332                                // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    352333                                // 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 );
    354335                                renameTypes( newAlt.expr );
    355336                                addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
     
    361342        }
    362343
    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 ) {
    364345                if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
    365346                        // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
     
    367348                        std::string tmp;
    368349                        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 ) );
    371351                        } // if
    372352                } // if
     
    374354
    375355        void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) {
    376                 alternatives.push_back( Alternative{ applicationExpr->clone(), env } );
     356                alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) );
    377357        }
    378358
     
    430410        Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
    431411                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() );
    434414
    435415                Cost convCost = Cost::zero;
    436                 std::list< DeclarationWithType* >& formals = function->parameters;
     416                std::list< DeclarationWithType* >& formals = function->get_parameters();
    437417                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();
    442422                        PRINT(
    443423                                std::cerr << "actual expression:" << std::endl;
    444                                 actualExpr->print( std::cerr, 8 );
     424                                (*actualExpr)->print( std::cerr, 8 );
    445425                                std::cerr << "--- results are" << std::endl;
    446426                                actualType->print( std::cerr, 8 );
    447427                        )
    448428                        if ( formal == formals.end() ) {
    449                                 if ( function->isVarArgs ) {
     429                                if ( function->get_isVarArgs() ) {
    450430                                        convCost.incUnsafe();
    451431                                        PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; )
    452432                                        // convert reference-typed expressions to value-typed expressions
    453                                         referenceToRvalueConversion( actualExpr, convCost );
     433                                        referenceToRvalueConversion( *actualExpr, convCost );
    454434                                        continue;
    455435                                } else {
     
    457437                                }
    458438                        }
    459                         if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( actualExpr ) ) {
     439                        if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) {
    460440                                // default arguments should be free - don't include conversion cost.
    461441                                // Unwrap them here because they are not relevant to the rest of the system.
    462                                 actualExpr = def->expr;
     442                                *actualExpr = def->expr;
    463443                                ++formal;
    464444                                continue;
    465445                        }
    466                         // mark conversion cost to formal and also specialization cost of formal type
    467446                        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 );
    470448                        ++formal; // can't be in for-loop update because of the continue
    471449                }
     
    474452                }
    475453
    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 ) {
    489455                        convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env );
    490456                }
     
    500466                                needAssertions[ *assert ].isUsed = true;
    501467                        }
    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        }
    507585
    508586        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//          )
    525613        }
    526614
     
    863951                }
    864952                // build and validate new alternative
    865                 Alternative newAlt{ appExpr, result.env, result.openVars, result.need, cost };
     953                Alternative newAlt( appExpr, result.env, cost );
    866954                PRINT(
    867955                        std::cerr << "instantiate function success: " << appExpr << std::endl;
     
    869957                        printAssertionSet( result.need, std::cerr, 8 );
    870958                )
    871                 inferParameters( newAlt, out );
     959                inferParameters( result.need, result.have, newAlt, result.openVars, out );
    872960        }
    873961
     
    11141202
    11151203                // 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 findMinCost
     1204                // for implicitconversions to each of the anonymous members, must happen after findMinCost
    11171205                // since anon conversions are never the cheapest expression
    11181206                for ( const Alternative & alt : winners ) {
     
    11461234                        if ( isLvalue( alt.expr ) ) {
    11471235                                alternatives.push_back(
    1148                                         Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } );
     1236                                        Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } );
    11491237                        } // if
    11501238                } // for
     
    11521240
    11531241        void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) {
    1154                 alternatives.push_back( Alternative{ expr->clone(), env } );
     1242                alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } );
    11551243        }
    11561244
     
    11971285                AltList candidates;
    11981286                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;
    12021289
    12031290                        alt.env.extractOpenVars( openVars );
     
    12271314                                // count one safe conversion for each value that is thrown away
    12281315                                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 ) );
    12331320                        } // if
    12341321                } // for
     
    12431330
    12441331        void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) {
    1245                 assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." );
     1332                assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." );
    12461333                AlternativeFinder finder( indexer, env );
    12471334                // don't prune here, since it's guaranteed all alternatives will have the same type
    12481335                finder.findWithoutPrune( castExpr->get_arg() );
    12491336                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 ) );
    12531340                }
    12541341        }
     
    12781365                        // find member of the given type
    12791366                        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) );
    12811368                        } 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) );
    12831370                        } 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() );
    12851372                        } // if
    12861373                } // for
     
    12881375
    12891376        void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) {
    1290                 alternatives.push_back( Alternative{ memberExpr->clone(), env } );
     1377                alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) );
    12911378        }
    12921379
     
    13011388                        // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    13021389                        // 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 );
    13041391                        PRINT(
    13051392                                std::cerr << "decl is ";
     
    13191406                // not sufficient to clone here, because variable's type may have changed
    13201407                // 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 ) );
    13221409        }
    13231410
    13241411        void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) {
    1325                 alternatives.push_back( Alternative{ constantExpr->clone(), env } );
     1412                alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) );
    13261413        }
    13271414
     
    13291416                if ( sizeofExpr->get_isType() ) {
    13301417                        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 ) );
    13331419                } else {
    13341420                        // find all alternatives for the argument to sizeof
     
    13441430                        Alternative &choice = winners.front();
    13451431                        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 ) );
    13481433                } // if
    13491434        }
     
    13521437                if ( alignofExpr->get_isType() ) {
    13531438                        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 ) );
    13561440                } else {
    13571441                        // find all alternatives for the argument to sizeof
     
    13671451                        Alternative &choice = winners.front();
    13681452                        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 ) );
    13711454                } // if
    13721455        }
     
    13781461                for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    13791462                        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 ) );
    13821464                                renameTypes( alternatives.back().expr );
    13831465                        } else {
     
    13981480
    13991481        void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) {
    1400                 alternatives.push_back( Alternative{ offsetofExpr->clone(), env } );
     1482                alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) );
    14011483        }
    14021484
    14031485        void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) {
    1404                 alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } );
     1486                alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) );
    14051487        }
    14061488
     
    14221504                                Cost cost = Cost::zero;
    14231505                                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 ) );
    14271507                                for ( DeclarationWithType * retVal : function->returnVals ) {
    14281508                                        alternatives.back().expr->result = retVal->get_type()->clone();
     
    14631543                                Cost cost = Cost::zero;
    14641544                                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 ) );
    14671546                                renameTypes( alternatives.back().expr );
    14681547                        } // for
     
    14791558                for ( const Alternative & first : firstFinder.alternatives ) {
    14801559                        for ( const Alternative & second : secondFinder.alternatives ) {
    1481                                 TypeEnvironment compositeEnv{ first.env };
     1560                                TypeEnvironment compositeEnv;
     1561                                compositeEnv.simpleCombine( first.env );
    14821562                                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 ) );
    14941566                        }
    14951567                }
     
    15121584                        for ( const Alternative & second : secondFinder.alternatives ) {
    15131585                                for ( const Alternative & third : thirdFinder.alternatives ) {
    1514                                         TypeEnvironment compositeEnv{ first.env };
     1586                                        TypeEnvironment compositeEnv;
     1587                                        compositeEnv.simpleCombine( first.env );
    15151588                                        compositeEnv.simpleCombine( second.env );
    15161589                                        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
    15261591                                        // 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 );
    15271595                                        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() );
    15321598                                                newExpr->result = commonType ? commonType : second.expr->result->clone();
    15331599                                                // 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 ) );
    15441604                                        } // if
    15451605                                } // for
     
    15541614                secondFinder.findWithAdjustment( commaExpr->get_arg2() );
    15551615                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 ) );
    15581617                } // for
    15591618                delete newFirstArg;
     
    15701629                for ( const Alternative & first : firstFinder.alternatives ) {
    15711630                        for ( const Alternative & second : secondFinder.alternatives ) {
    1572                                 TypeEnvironment compositeEnv{ first.env };
     1631                                TypeEnvironment compositeEnv;
     1632                                compositeEnv.simpleCombine( first.env );
    15731633                                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 );
    15811637                                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() );
    15861640                                        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 ) );
    15911643                                } // if
    15921644                        } // for
     
    16061658
    16071659                        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 ) } );
    16191663                } // for
    16201664        }
    16211665
    16221666        void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) {
    1623                 alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
     1667                alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    16241668        }
    16251669
    16261670        void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    1627                 alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } );
     1671                alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );
    16281672        }
    16291673
     
    16341678                finder.findWithoutPrune( ctorExpr->get_callExpr() );
    16351679                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 ) );
    16381681                }
    16391682        }
    16401683
    16411684        void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) {
    1642                 alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
     1685                alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    16431686        }
    16441687
    16451688        void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) {
    1646                 alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } );
     1689                alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) );
    16471690        }
    16481691
     
    16531696                        // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked"
    16541697                        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 ) );
    16561699                }
    16571700        }
     
    16611704                ResolvExpr::resolveStmtExpr( newStmtExpr, indexer );
    16621705                // 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 ) );
    16641707        }
    16651708
     
    16831726                        for ( Alternative & alt : finder.get_alternatives() ) {
    16841727                                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?
    16911730                                PRINT(
    16921731                                        std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
    16931732                                )
    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.
    16991737                                int discardedValues = alt.expr->result->size() - toType->size();
    17001738                                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]))
    17051741                                // 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??
    17081743
    17091744                                Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv );
     
    17111746                                        // count one safe conversion for each value that is thrown away
    17121747                                        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 ) );
    17191750                                }
    17201751                        }
  • src/ResolvExpr/AlternativeFinder.h

    r276a55b2 r07ec1a2  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:56:12 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Fri Oct -5 10:01:00 2018
    13 // Update Count     : 5
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Jul 26 11:24:00 2017
     13// Update Count     : 4
    1414//
    1515
     
    2424#include "ResolvExpr/Cost.h"             // for Cost, Cost::infinity
    2525#include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
    26 #include "ResolvMode.h"                  // for ResolvMode
    2726#include "SynTree/Visitor.h"             // for Visitor
    2827#include "SynTree/SynTree.h"             // for Visitor Nodes
     
    6968                }
    7069
    71                 void find( Expression *expr, ResolvMode mode = ResolvMode{} );
     70                void find( Expression *expr, bool adjust = false, bool prune = true, bool failFast = true );
    7271                /// Calls find with the adjust flag set; adjustment turns array and function types into equivalent pointer types
    7372                void findWithAdjustment( Expression *expr );
  • src/ResolvExpr/ConversionCost.cc

    r276a55b2 r07ec1a2  
    2828
    2929namespace 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 );
    3836
    3937#if 0
  • src/ResolvExpr/Cost.h

    r276a55b2 r07ec1a2  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 09:39:50 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Fri Oct 05 14:32:00 2018
    13 // Update Count     : 7
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Jul 22 09:35:55 2017
     13// Update Count     : 5
    1414//
    1515
     
    2121        class Cost {
    2222          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 );
    2524
    2625          public:
     
    2827                Cost & incPoly( int inc = 1 );
    2928                Cost & incSafe( int inc = 1 );
    30                 Cost & incVar( int inc = 1 );
    31                 Cost & decSpec( int inc = 1 );
    3229                Cost & incReference( int inc = 1 );
    3330
     
    3532                int get_polyCost() const { return polyCost; }
    3633                int get_safeCost() const { return safeCost; }
    37                 int get_varCost() const { return varCost; }
    38                 int get_specCost() const { return specCost; }
    3934                int get_referenceCost() const { return referenceCost; }
    4035
     
    4641                bool operator!=( const Cost &other ) const;
    4742                friend std::ostream &operator<<( std::ostream &os, const Cost &cost );
    48                 // returns negative for *this < other, 0 for *this == other, positive for *this > other
    49                 int compare( const Cost &other ) const;
    5043
    5144                static const Cost zero;
     
    5548                static const Cost poly;
    5649                static const Cost safe;
    57                 static const Cost var;
    58                 static const Cost spec;
    5950                static const Cost reference;
     51          private:
     52                int compare( const Cost &other ) const;
    6053
    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;
    6858        };
    6959
    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 ) {}
    7461
    7562        inline Cost & Cost::incUnsafe( int inc ) {
     
    9178        }
    9279
    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 
    10580        inline Cost & Cost::incReference( int inc ) {
    10681                if ( *this == infinity ) return *this;
     
    11186        inline Cost Cost::operator+( const Cost &other ) const {
    11287                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 );
    11789        }
    11890
    11991        inline Cost Cost::operator-( const Cost &other ) const {
    12092                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 );
    12594        }
    12695
     
    134103                polyCost += other.polyCost;
    135104                safeCost += other.safeCost;
    136                 varCost += other.varCost;
    137                 specCost += other.specCost;
    138105                referenceCost += other.referenceCost;
    139106                return *this;
     
    156123                } else if ( safeCost < other.safeCost ) {
    157124                        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;
    166125                } else if ( referenceCost > other.referenceCost ) {
    167126                        return false;
     
    173132        }
    174133
    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 
    187134        inline bool Cost::operator==( const Cost &other ) const {
    188135                return unsafeCost == other.unsafeCost
    189136                        && polyCost == other.polyCost
    190137                        && safeCost == other.safeCost
    191                         && varCost == other.varCost
    192                         && specCost == other.specCost
    193138                        && referenceCost == other.referenceCost;
    194139        }
     
    199144
    200145        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;
    204148        }
    205149} // namespace ResolvExpr
  • src/ResolvExpr/Resolver.cc

    r276a55b2 r07ec1a2  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Fri Oct 05 09:43:00 2018
    13 // Update Count     : 214
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Feb 17 11:19:40 2018
     13// Update Count     : 213
    1414//
    1515
     16#include <stddef.h>                      // for NULL
    1617#include <cassert>                       // for strict_dynamic_cast, assert
    1718#include <memory>                        // for allocator, allocator_traits<...
    1819#include <tuple>                         // for get
    19 #include <vector>                        // for vector
     20#include <vector>
    2021
    2122#include "Alternative.h"                 // for Alternative, AltList
     
    3031#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    3132#include "Resolver.h"
    32 #include "ResolvMode.h"                  // for ResolvMode
    3333#include "SymTab/Autogen.h"              // for SizeType
    3434#include "SymTab/Indexer.h"              // for Indexer
     
    168168
    169169        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) {
    171171                        assertf( untyped, "expected a non-null expression." );
    172 
    173                         // xxx - this isn't thread-safe, but should work until we parallelize the resolver
    174                         static unsigned recursion_level = 0;
    175 
    176                         ++recursion_level;
    177172                        TypeEnvironment env;
    178173                        AlternativeFinder finder( indexer, env );
    179                         finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
    180                         --recursion_level;
     174                        finder.find( untyped, adjust, prune, failFast );
    181175
    182176                        #if 0
     
    191185                        #endif
    192186
    193                         // produce filtered list of alternatives
    194187                        AltList candidates;
    195188                        for ( Alternative & alt : finder.get_alternatives() ) {
     
    199192                        }
    200193
    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 ) {
    203199                                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 ) {
    240201                                std::ostringstream stream;
    241202                                stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
     
    246207                        }
    247208
    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 ) ) {
    253212                                SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
    254213                        }
    255 
    256                         // xxx - check for ambiguous expressions
    257                        
    258                         // output selected choice
    259214                        alt = std::move( choice );
    260215                }
    261216
    262217                /// 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) {
    264219                        if ( ! untyped ) return;
    265220                        Alternative choice;
    266                         findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode );
     221                        findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast );
    267222                        finishExpr( choice.expr, choice.env, untyped->env );
    268223                        delete untyped;
     
    295250                untyped.arg = expr;
    296251                Alternative choice;
    297                 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() );
     252                findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true );
    298253                CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
    299254                env = std::move( choice.env );
     
    402357
    403358        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 object
    407                 // declarations in the return and parameter types. So each value of initContext is
    408                 // retained, so the type on the first analysis is preserved and used for selecting the RHS.
     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.
    409364                GuardValue( currentObject );
    410365                currentObject = CurrentObject( objectDecl->get_type() );
     
    442397
    443398        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.
    448402                for ( Declaration * d : functionDecl->type->parameters ) {
    449403                        if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
     
    795749                initExpr->expr = nullptr;
    796750                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.
    800753                newExpr->spliceInferParams( initExpr );
    801754                delete initExpr;
    802755
    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)
    805757                Type * initContext = currentObject.getCurrentType();
    806758
     
    814766                                        if ( isCharType( pt->get_base() ) ) {
    815767                                                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";
    818769                                                        newExpr = ce->get_arg();
    819770                                                        ce->set_arg( nullptr );
     
    837788                // move cursor into brace-enclosed initializer-list
    838789                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
    841791                std::list<Designation *> newDesignations;
    842792                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 resolving the 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.
    845795                        Designation * des = std::get<0>(p);
    846796                        Initializer * init = std::get<1>(p);
     
    872822                // fall back on C-style initializer
    873823                delete ctorInit->get_ctor();
    874                 ctorInit->set_ctor( nullptr );
     824                ctorInit->set_ctor( NULL );
    875825                delete ctorInit->get_dtor();
    876                 ctorInit->set_dtor( nullptr );
     826                ctorInit->set_dtor( NULL );
    877827                maybeAccept( ctorInit->get_init(), *visitor );
    878828        }
     
    917867
    918868                // xxx - todo -- what about arrays?
    919                 // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
     869                // if ( dtor == NULL && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
    920870                //      // can reduce the constructor down to a SingleInit using the
    921871                //      // second argument from the ctor call, since
    922872                //      delete ctorInit->get_ctor();
    923                 //      ctorInit->set_ctor( nullptr );
     873                //      ctorInit->set_ctor( NULL );
    924874
    925875                //      Expression * arg =
  • src/ResolvExpr/TypeEnvironment.cc

    r276a55b2 r07ec1a2  
    120120
    121121        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 ) {
    123123                        if ( i->vars.find( var ) != i->vars.end() ) return &*i;
    124124                } // for
     
    168168
    169169        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 ) {
    171171                        for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) {
    172172                                if ( theClass->type ) {
     
    188188        }
    189189
    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 ) {
    192192                        if ( i->vars.count( var ) ) return i;
    193193                } // for
     
    199199        }
    200200
    201         // xxx -- this should maybe be worrying about iterator invalidation (see resolv-proto)
    202         bool TypeEnvironment::mergeBound( EqvClass& to, const EqvClass& from, OpenVarSet& openVars, const SymTab::Indexer& indexer ) {
    203                 if ( from.type ) {
    204                         if ( to.type ) {
    205                                 // attempt to unify bound types
    206                                 std::unique_ptr<Type> toType{ to.type->clone() }, fromType{ from.type->clone() };
    207                                 WidenMode widenMode{ to.allowWidening, from.allowWidening };
    208                                 Type* common = nullptr;
    209                                 AssertionSet need, have;
    210                                 if ( unifyInexact( toType.get(), fromType.get(), *this, need, have, openVars, widenMode, indexer, common ) ) {
    211                                         // unifies, set common type if necessary
    212                                         if ( common ) {
    213                                                 common->get_qualifiers() = Type::Qualifiers{};
    214                                                 to.set_type( common );
    215                                         }
    216                                 } else return false; // cannot unify
    217                         } else {
    218                                 to.type = from.type->clone();
    219                         }
    220                 }
    221 
    222                 // unify widening if matches
    223                 to.allowWidening &= from.allowWidening;
    224                 return true;
    225         }
    226 
    227         // xxx -- this should maybe be worrying about iterator invalidation (see resolv-proto)
    228         bool TypeEnvironment::mergeClasses( TypeEnvironment::ClassList::iterator to, TypeEnvironment::ClassList::iterator from, OpenVarSet& openVars, const SymTab::Indexer& indexer ) {
    229                 EqvClass& r = *to;
    230                 EqvClass& s = *from;
    231 
    232                 // ensure bounds match
    233                 if ( ! mergeBound( r, s, openVars, indexer ) ) return false;
    234 
    235                 // check safely bindable
    236                 if ( r.type && occursIn( r.type, s.vars.begin(), s.vars.end(), *this ) ) return false;
    237                
    238                 // merge classes in
    239                 r.vars.insert( s.vars.begin(), s.vars.end() );
    240                 r.allowWidening &= s.allowWidening;
    241                 env.erase( from );
    242 
    243                 return true;
    244         }
    245 
    246         bool TypeEnvironment::combine( const TypeEnvironment& o, OpenVarSet& openVars, const SymTab::Indexer& indexer ) {
    247                 // short-circuit easy cases
    248                 if ( o.isEmpty() ) return true;
    249                 if ( isEmpty() ) {
    250                         simpleCombine( o );
    251                         return true;
    252                 }
    253 
    254                 // merge classes
    255                 for ( auto ct = o.env.begin(); ct != o.env.end(); ++ct ) {
    256                         const EqvClass& c = *ct;
    257 
    258                         // typeclass in local environment bound to c
    259                         auto rt = env.end();
    260 
    261                         // look for first existing bound variable
    262                         auto vt = c.vars.begin();
    263                         for ( ; vt != c.vars.end(); ++vt ) {
    264                                 rt = internal_lookup( *vt );
    265                                 if ( rt != env.end() ) break;
    266                         }
    267 
    268                         if ( rt != env.end() ) {  // c needs to be merged into *rt
    269                                 EqvClass& r = *rt;
    270                                 // merge bindings
    271                                 if ( ! mergeBound( r, c, openVars, indexer ) ) return false;
    272                                 // merge previous unbound variables into this class, checking occurs if needed
    273                                 if ( r.type ) for ( auto ut = c.vars.begin(); ut != vt; ++ut ) {
    274                                         if ( occurs( r.type, *ut, *this ) ) return false;
    275                                         r.vars.insert( *ut );
    276                                 } else { r.vars.insert( c.vars.begin(), vt ); }
    277                                 // merge subsequent variables into this class (skipping *vt, already there)
    278                                 while ( ++vt != c.vars.end() ) {
    279                                         auto st = internal_lookup( *vt );
    280                                         if ( st == env.end() ) {
    281                                                 // unbound, safe to add if passes occurs
    282                                                 if ( r.type && occurs( r.type, *vt, *this ) ) return false;
    283                                                 r.vars.insert( *vt );
    284                                         } else if ( st != rt ) {
    285                                                 // bound, but not to the same class
    286                                                 if ( ! mergeClasses( rt, st, openVars, indexer ) ) return false;
    287                                         }   // ignore bound into the same class
    288                                 }
    289                         } else {  // no variables in c bound; just copy up
    290                                 env.push_back( c );
    291                         }
    292                 }
    293 
    294                 // merged all classes
    295                 return true;
    296         }
    297 
    298201        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 ) {
    300203                        for ( std::set< std::string >::const_iterator var = eqvClass->vars.begin(); var != eqvClass->vars.end(); ++var ) {
    301204                                openVars[ *var ] = eqvClass->data;
  • src/ResolvExpr/TypeEnvironment.h

    r276a55b2 r07ec1a2  
    3939        // declarations.
    4040        //
    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.
    4342        //
    4443        // Note: since this compares pointers for position, minor changes in the source file that affect
    4544        // memory layout can alter compilation time in unpredictable ways. For example, the placement
    4645        // 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.
    5351        struct AssertCompare {
    5452                bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const {
     
    5957        };
    6058        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;
    6564        };
    6665        typedef std::map< DeclarationWithType*, AssertionSetValue, AssertCompare > AssertionSet;
    6766        typedef std::map< std::string, TypeDecl::Data > OpenVarSet;
    68 
    69         /// merges one set of open vars into another
    70         static inline void mergeOpenVars( OpenVarSet& dst, const OpenVarSet& src ) {
    71                 for ( const auto& entry : src ) { dst[ entry.first ] = entry.second; }
    72         }
    7367
    7468        void printAssertionSet( const AssertionSet &, std::ostream &, int indent = 0 );
     
    9791
    9892        class TypeEnvironment {
    99                 using ClassList = std::list< EqvClass >;
    10093          public:
    10194                const EqvClass* lookup( const std::string &var ) const;
     
    110103                bool isEmpty() const { return env.empty(); }
    111104                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* ) );
    114106                void simpleCombine( const TypeEnvironment &second );
    115 
    116           private:
    117                 /// Unifies the type bound of to with the type bound of from, returning false if fails
    118                 bool mergeBound( EqvClass& to, const EqvClass& from, OpenVarSet& openVars, const SymTab::Indexer& indexer );
    119 
    120                 /// Merges two type classes from local environment, returning false if fails
    121                 bool mergeClasses( ClassList::iterator to, ClassList::iterator from, OpenVarSet& openVars, const SymTab::Indexer& indexer );
    122 
    123           public:
    124                 /// Merges the second environment with this one, checking compatibility.
    125                 /// Returns false if fails, but does NOT roll back partial changes.
    126                 bool combine( const TypeEnvironment& second, OpenVarSet& openVars, const SymTab::Indexer& indexer );
    127                
    128107                void extractOpenVars( OpenVarSet &openVars ) const;
    129108                TypeEnvironment *clone() const { return new TypeEnvironment( *this ); }
     
    144123                void forbidWidening();
    145124
    146                 using iterator = ClassList::const_iterator;
     125                using iterator = std::list< EqvClass >::const_iterator;
    147126                iterator begin() const { return env.begin(); }
    148127                iterator end() const { return env.end(); }
    149128
    150129          private:
    151                 ClassList env;
     130                std::list< EqvClass > env;
    152131               
    153                 ClassList::iterator internal_lookup( const std::string &var );
     132                std::list< EqvClass >::iterator internal_lookup( const std::string &var );
    154133        };
    155134
  • src/ResolvExpr/module.mk

    r276a55b2 r07ec1a2  
    3333       ResolvExpr/TypeEnvironment.cc \
    3434       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  
    7272        Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
    7373
    74         // in AlternativeFinder.cc
    75         Cost computeConversionCost( Type *actualType, Type *formalType,
    76                 const SymTab::Indexer &indexer, const TypeEnvironment &env );
    77 
    7874        // in PtrsAssignable.cc
    7975        int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env );
     
    106102        int polyCost( Type *type, const TypeEnvironment &env, const SymTab::Indexer &indexer );
    107103
    108         // in SpecCost.cc
    109         int specCost( Type *type );
    110 
    111104        // in Occurs.cc
    112105        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         }
    122106
    123107        // in AlternativeFinder.cc
  • src/SynTree/ApplicationExpr.cc

    r276a55b2 r07ec1a2  
    2929
    3030ParamEntry::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 ) ) {
    3232}
    3333
     
    3939        formalType = maybeClone( other.formalType );
    4040        expr = maybeClone( other.expr );
    41         // *inferParams = *other.inferParams;
     41        *inferParams = *other.inferParams;
    4242        return *this;
    4343}
     
    5050
    5151ParamEntry::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 ) ) {
    5353        other.actualType = nullptr;
    5454        other.formalType = nullptr;
     
    6868        other.formalType = nullptr;
    6969        other.expr = nullptr;
    70         // inferParams = std::move( other.inferParams );
     70        inferParams = std::move( other.inferParams );
    7171        return *this;
    7272}
  • src/SynTree/Expression.cc

    r276a55b2 r07ec1a2  
    4040                        Declaration::declFromId( i->second.decl )->printShort( os, indent+1 );
    4141                        os << std::endl;
    42                         printInferParams( i->second.expr->inferParams, os, indent+1, level+1 );
     42                        printInferParams( *i->second.inferParams, os, indent+1, level+1 );
    4343                } // for
    4444        } // if
     
    4747Expression::Expression() : result( 0 ), env( 0 ) {}
    4848
    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 ) {}
     49Expression::Expression( const Expression &other ) : BaseSyntaxNode( other ), result( maybeClone( other.result ) ), env( maybeClone( other.env ) ), extension( other.extension ), inferParams( other.inferParams ) {
     50}
    5051
    5152void Expression::spliceInferParams( Expression * other ) {
     
    5455                inferParams[p.first] = std::move( p.second );
    5556        }
    56         resnSlots.insert( resnSlots.end(), other->resnSlots.begin(), other->resnSlots.end() );
    5757}
    5858
  • src/SynTree/Expression.h

    r276a55b2 r07ec1a2  
    2121#include <memory>                 // for allocator, unique_ptr
    2222#include <string>                 // for string
    23 #include <vector>                 // for vector
    2423
    2524#include "BaseSyntaxNode.h"       // for BaseSyntaxNode
     
    3938/// but subject to decay-to-pointer and type parameter renaming
    4039struct 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 ) {}
    4342        ParamEntry( const ParamEntry & other );
    4443        ParamEntry( ParamEntry && other );
     
    5150        Type * formalType;
    5251        Expression * expr;
    53         // std::unique_ptr< InferredParams > inferParams;
     52        std::unique_ptr< InferredParams > inferParams;
    5453};
    5554
     
    6059        TypeSubstitution * env;
    6160        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;
    6662
    6763        Expression();
     
    7773        bool get_extension() const { return extension; }
    7874        Expression * set_extension( bool exten ) { extension = exten; return this; }
     75
     76        InferredParams & get_inferParams() { return inferParams; }
    7977
    8078        // move other's inferParams to this
  • src/Tuples/Explode.h

    r276a55b2 r07ec1a2  
    4444        template<typename OutputIterator>
    4545        void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env,
    46                         const ResolvExpr::OpenVarSet& openVars, const ResolvExpr::AssertionList& need,
    4746                        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 };
    4948        }
    5049
    5150        /// Append alternative to an ExplodedActual
    5251        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& ) {
    5553                ea.exprs.emplace_back( expr );
    56                 /// xxx -- merge environment, openVars, need, cost?
     54                /// xxx -- merge environment, cost?
    5755        }
    5856
     
    7068                                        // distribute reference cast over all components
    7169                                        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 );
    7371                                }
    7472                                // 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)
     
    104102                } else {
    105103                        // 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 );
    108105                }
    109106        }
  • src/Tuples/TupleAssignment.cc

    r276a55b2 r07ec1a2  
    6262                struct Matcher {
    6363                  public:
    64                         Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,
    65                                 const ResolvExpr::AltList& rhs );
     64                        Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const
     65                                ResolvExpr::AltList& rhs );
    6666                        virtual ~Matcher() {}
    67                        
    6867                        virtual void match( std::list< Expression * > &out ) = 0;
    6968                        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                        
    8169                        ResolvExpr::AltList lhs, rhs;
    8270                        TupleAssignSpotter &spotter;
     
    8472                        std::list< ObjectDecl * > tmpDecls;
    8573                        ResolvExpr::TypeEnvironment compositeEnv;
    86                         ResolvExpr::OpenVarSet openVars;
    87                         ResolvExpr::AssertionSet need;
    8874                };
    8975
     
    259245                }
    260246
    261                 // extract expressions from the assignment alternatives to produce a list of assignments
    262                 // that together form a single alternative
     247                // extract expressions from the assignment alternatives to produce a list of assignments that
     248                // together form a single alternative
    263249                std::list< Expression *> solved_assigns;
    264250                for ( ResolvExpr::Alternative & alt : current ) {
    265251                        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 );
    269255                // 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 ) );
    275259        }
    276260
     
    279263        : lhs(lhs), rhs(rhs), spotter(spotter),
    280264          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 );
    283267        }
    284268
  • tests/.expect/castError.txt

    r276a55b2 r07ec1a2  
    44... to:
    55  char Alternatives are:
    6 Cost ( 1, 0, 0, 0, 0, 0 ): Cast of:
     6Cost ( 1, 0, 0, 0 ): Cast of:
    77     Variable Expression: f: function
    88       accepting unspecified arguments
     
    1616 Environment:
    1717
    18 Cost ( 1, 0, 0, 0, 0, 0 ): Cast of:
     18Cost ( 1, 0, 0, 0 ): Cast of:
    1919     Variable Expression: f: double
    2020   ... to:
     
    2525 Environment:
    2626
    27 Cost ( 1, 0, 0, 0, 0, 0 ): Cast of:
     27Cost ( 1, 0, 0, 0 ): Cast of:
    2828     Variable Expression: f: signed int
    2929   ... to:
  • tests/searchsort.cfa

    r276a55b2 r07ec1a2  
    5757
    5858        // descending sort/search by changing < to >
    59         for ( i; 0 ~ size ) {
     59        for ( i; 0u ~ size ) {
    6060                iarr[i] = i + 1;
    6161                sout | iarr[i] | ", ";
Note: See TracChangeset for help on using the changeset viewer.