Changeset 276a55b2


Ignore:
Timestamp:
Jan 14, 2019, 3:38:28 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, no_list, persistent-indexer, pthread-emulation, qualifiedEnum
Children:
fd73248
Parents:
07ec1a2 (diff), 52ffa30 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
5 added
23 edited

Legend:

Unmodified
Added
Removed
  • src/Common/utility.h

    r07ec1a2 r276a55b2  
    2626#include <string>
    2727#include <type_traits>
     28#include <utility>
    2829
    2930#include <cassert>
     
    462463std::pair<long long int, bool> eval(Expression * expr);
    463464
     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.
     469template<typename Iter, typename Compare>
     470Iter 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
     488template<typename Iter, typename Compare>
     489inline 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
     494template<typename Iter>
     495inline Iter sort_mins( Iter begin, Iter end ) {
     496        return sort_mins( begin, end, std::less<typename std::iterator_traits<Iter>::value_type>{} );
     497}
     498
    464499// Local Variables: //
    465500// tab-width: 4 //
  • src/GenPoly/Box.cc

    r07ec1a2 r276a55b2  
    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->get_inferParams().find( (*assert)->get_uniqueId() );
    801                                         assertf( inferParam != appExpr->get_inferParams().end(), "addInferredParams missing inferred parameter: %s in: %s", toString( *assert ).c_str(), toString( appExpr ).c_str() );
     800                                        InferredParams::const_iterator inferParam = appExpr->inferParams.find( (*assert)->get_uniqueId() );
     801                                        assertf( inferParam != appExpr->inferParams.end(), "addInferredParams missing inferred parameter: %s in: %s", toString( *assert ).c_str(), toString( appExpr ).c_str() );
    802802                                        Expression *newExpr = inferParam->second.expr->clone();
    803803                                        addCast( newExpr, (*assert)->get_type(), tyVars );
  • src/GenPoly/Specialize.cc

    r07ec1a2 r276a55b2  
    245245                appExpr->env = TypeSubstitution::newFromExpr( appExpr, env );
    246246                if ( inferParams ) {
    247                         appExpr->get_inferParams() = *inferParams;
     247                        appExpr->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->get_inferParams() );
     286                        *actual = doSpecialization( (*formal)->get_type(), *actual, &appExpr->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->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) {
    298                                 inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, inferParam->second.inferParams.get() );
     297                        for ( InferredParams::iterator inferParam = appExpr->inferParams.begin(); inferParam != appExpr->inferParams.end(); ++inferParam ) {
     298                                inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &inferParam->second.expr->inferParams );
    299299                        }
    300300                }
  • src/Makefile.am

    r07ec1a2 r276a55b2  
    127127  ResolvExpr/PtrsCastable.cc \
    128128  ResolvExpr/RenameVars.cc \
     129  ResolvExpr/ResolveAssertions.cc \
    129130  ResolvExpr/Resolver.cc \
    130131  ResolvExpr/ResolveTypeof.cc \
     132  ResolvExpr/SpecCost.cc \
    131133  ResolvExpr/TypeEnvironment.cc \
    132134  ResolvExpr/Unify.cc \
  • src/Makefile.in

    r07ec1a2 r276a55b2  
    206206        ResolvExpr/PtrsAssignable.$(OBJEXT) \
    207207        ResolvExpr/PtrsCastable.$(OBJEXT) \
    208         ResolvExpr/RenameVars.$(OBJEXT) ResolvExpr/Resolver.$(OBJEXT) \
     208        ResolvExpr/RenameVars.$(OBJEXT) \
     209        ResolvExpr/ResolveAssertions.$(OBJEXT) \
     210        ResolvExpr/Resolver.$(OBJEXT) \
    209211        ResolvExpr/ResolveTypeof.$(OBJEXT) \
     212        ResolvExpr/SpecCost.$(OBJEXT) \
    210213        ResolvExpr/TypeEnvironment.$(OBJEXT) \
    211214        ResolvExpr/Unify.$(OBJEXT) SymTab/Autogen.$(OBJEXT) \
     
    262265        ResolvExpr/TypeEnvironment.$(OBJEXT) \
    263266        ResolvExpr/CurrentObject.$(OBJEXT) \
    264         ResolvExpr/ExplodedActual.$(OBJEXT) SymTab/Indexer.$(OBJEXT) \
    265         SymTab/Mangler.$(OBJEXT) SymTab/ManglerCommon.$(OBJEXT) \
    266         SymTab/Validate.$(OBJEXT) SymTab/FixFunction.$(OBJEXT) \
    267         SymTab/Autogen.$(OBJEXT) SynTree/Type.$(OBJEXT) \
    268         SynTree/VoidType.$(OBJEXT) SynTree/BasicType.$(OBJEXT) \
    269         SynTree/PointerType.$(OBJEXT) SynTree/ArrayType.$(OBJEXT) \
    270         SynTree/ReferenceType.$(OBJEXT) SynTree/FunctionType.$(OBJEXT) \
     267        ResolvExpr/ExplodedActual.$(OBJEXT) \
     268        ResolvExpr/SpecCost.$(OBJEXT) \
     269        ResolvExpr/ResolveAssertions.$(OBJEXT) \
     270        SymTab/Indexer.$(OBJEXT) SymTab/Mangler.$(OBJEXT) \
     271        SymTab/ManglerCommon.$(OBJEXT) SymTab/Validate.$(OBJEXT) \
     272        SymTab/FixFunction.$(OBJEXT) SymTab/Autogen.$(OBJEXT) \
     273        SynTree/Type.$(OBJEXT) SynTree/VoidType.$(OBJEXT) \
     274        SynTree/BasicType.$(OBJEXT) SynTree/PointerType.$(OBJEXT) \
     275        SynTree/ArrayType.$(OBJEXT) SynTree/ReferenceType.$(OBJEXT) \
     276        SynTree/FunctionType.$(OBJEXT) \
    271277        SynTree/ReferenceToType.$(OBJEXT) SynTree/TupleType.$(OBJEXT) \
    272278        SynTree/TypeofType.$(OBJEXT) SynTree/AttrType.$(OBJEXT) \
     
    589595        ResolvExpr/Occurs.cc ResolvExpr/TypeEnvironment.cc \
    590596        ResolvExpr/CurrentObject.cc ResolvExpr/ExplodedActual.cc \
     597        ResolvExpr/SpecCost.cc ResolvExpr/ResolveAssertions.cc \
    591598        SymTab/Indexer.cc SymTab/Mangler.cc SymTab/ManglerCommon.cc \
    592599        SymTab/Validate.cc SymTab/FixFunction.cc SymTab/Autogen.cc \
     
    696703  ResolvExpr/PtrsCastable.cc \
    697704  ResolvExpr/RenameVars.cc \
     705  ResolvExpr/ResolveAssertions.cc \
    698706  ResolvExpr/Resolver.cc \
    699707  ResolvExpr/ResolveTypeof.cc \
     708  ResolvExpr/SpecCost.cc \
    700709  ResolvExpr/TypeEnvironment.cc \
    701710  ResolvExpr/Unify.cc \
     
    946955ResolvExpr/RenameVars.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    947956        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     957ResolvExpr/ResolveAssertions.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     958        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    948959ResolvExpr/Resolver.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    949960        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    950961ResolvExpr/ResolveTypeof.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     962        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
     963ResolvExpr/SpecCost.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
    951964        ResolvExpr/$(DEPDIR)/$(am__dirstamp)
    952965ResolvExpr/TypeEnvironment.$(OBJEXT): ResolvExpr/$(am__dirstamp) \
     
    12071220@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/PtrsCastable.Po@am__quote@
    12081221@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@
    12091223@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/ResolveTypeof.Po@am__quote@
    12101224@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@
    12111226@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/TypeEnvironment.Po@am__quote@
    12121227@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/Unify.Po@am__quote@
  • src/ResolvExpr/Alternative.cc

    r07ec1a2 r276a55b2  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:44:23 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat May 16 23:54:23 2015
    13 // Update Count     : 2
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Thu Oct 11 10:55:00 2018
     13// Update Count     : 3
    1414//
    1515
     
    2020#include <utility>                       // for move
    2121
    22 #include "Common/utility.h"              // for maybeClone
     22#include "Common/utility.h"              // for cloneAll
    2323#include "ResolvExpr/Cost.h"             // for Cost, Cost::zero, operator<<
    2424#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
     
    2727
    2828namespace ResolvExpr {
    29         Alternative::Alternative() : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ) {}
     29        Alternative::Alternative()
     30        : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ), env(), openVars(), need() {}
    3031
    31         Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost )
    32                 : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ) {}
     32        Alternative::Alternative( Expression *expr, const TypeEnvironment &env )
     33        : cost( Cost::zero ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars(), need() {}
     34       
     35        Alternative::Alternative( const Alternative &o, Expression *expr, const Cost &cost )
     36        : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( o.env ), openVars( o.openVars ),
     37          need() { cloneAll( o.need, need ); }
    3338
    34         Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost, const Cost &cvtCost )
    35                 : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {}
     39        Alternative::Alternative( Expression *expr, const TypeEnvironment &env,
     40                const OpenVarSet& openVars, const AssertionList& oneed, const Cost& cost )
     41        : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars( openVars ),
     42          need() { cloneAll( oneed, need ); }
    3643
    37         Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) {
    38         }
     44        Alternative::Alternative( Expression *expr, const TypeEnvironment &env,
     45                const OpenVarSet& openVars, const AssertionList& oneed, const Cost& cost,
     46                const Cost &cvtCost )
     47        : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ), openVars( openVars ),
     48          need() { cloneAll( oneed, need ); }
     49       
     50        Alternative::Alternative( Expression *expr, const TypeEnvironment &env,
     51                const OpenVarSet &openVars, const AssertionSet &oneed, const Cost &cost)
     52        : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( env ), openVars( openVars ),
     53          need() { cloneAll( oneed, need ); }
     54       
     55        Alternative::Alternative( Expression *expr, const TypeEnvironment &env,
     56                const OpenVarSet &openVars, const AssertionSet &oneed, const Cost &cost,
     57                const Cost& cvtCost )
     58        : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ), openVars( openVars ),
     59          need() { cloneAll( oneed, need ); }
     60       
     61        Alternative::Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars,
     62                AssertionSet &&needSet, const Cost &cost )
     63        : cost( cost ), cvtCost( Cost::zero ), expr( expr ), env( std::move(env) ),
     64          openVars( std::move(openVars) ), need( needSet.begin(), needSet.end() ) {}
     65       
     66        Alternative::Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars,
     67                AssertionSet &&needSet, const Cost &cost, const Cost &cvtCost )
     68        : cost( cost ), cvtCost( cvtCost ), expr( expr ), env( std::move(env) ),
     69          openVars( std::move(openVars) ), need( needSet.begin(), needSet.end() ) {}
     70
     71        Alternative::Alternative( const Alternative &other )
     72        : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ),
     73          env( other.env ), openVars( other.openVars ), need() { cloneAll( other.need, need ); }
    3974
    4075        Alternative &Alternative::operator=( const Alternative &other ) {
     
    4580                expr = maybeClone( other.expr );
    4681                env = other.env;
     82                openVars = other.openVars;
     83                need.clear();
     84                cloneAll( other.need, need );
    4785                return *this;
    4886        }
    4987
    50         Alternative::Alternative( Alternative && other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), env( std::move( other.env ) ) {
    51                 other.expr = nullptr;
    52         }
     88        Alternative::Alternative( Alternative && other )
     89        : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ),
     90          env( std::move( other.env ) ), openVars( std::move( other.openVars ) ),
     91          need( std::move( other.need ) ) { other.expr = nullptr; }
    5392
    5493        Alternative & Alternative::operator=( Alternative && other ) {
     
    5998                expr = other.expr;
    6099                env = std::move( other.env );
     100                openVars = std::move( other.openVars );
     101                need = std::move( other.need );
    61102                other.expr = nullptr;
    62103                return *this;
     
    64105
    65106        Alternative::~Alternative() {
     107                for ( AssertionItem& n : need ) { delete n.decl; }
    66108                delete expr;
    67109        }
  • src/ResolvExpr/Alternative.h

    r07ec1a2 r276a55b2  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:45:43 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:36:36 2017
    13 // Update Count     : 3
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Thu Oct 11 10:55:00 2018
     13// Update Count     : 4
    1414//
    1515
     
    2020
    2121#include "Cost.h"             // for Cost
    22 #include "TypeEnvironment.h"  // for TypeEnvironment
     22#include "TypeEnvironment.h"  // for TypeEnvironment, AssertionSetValue
     23
     24#include "Common/utility.h"   // for maybeClone
    2325
    2426class Expression;
    2527
    2628namespace 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
    2770        struct Alternative {
    2871                Alternative();
    29                 Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost );
    30                 Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost, const Cost &cvtCost );
     72                Alternative( Expression *expr, const TypeEnvironment &env );
     73                Alternative( const Alternative &o, Expression *expr, const Cost &cost );
     74                Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet& openVars,
     75                        const AssertionList& need, const Cost &cost );
     76                Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet& openVars,
     77                        const AssertionList& need, const Cost &cost, const Cost &cvtCost );
     78                Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet &openVars,
     79                        const AssertionSet &need, const Cost &cost);
     80                Alternative( Expression *expr, const TypeEnvironment &env, const OpenVarSet &openVars,
     81                        const AssertionSet &need, const Cost &cost, const Cost& cvtCost );
     82                Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars,
     83                        AssertionSet &&need, const Cost &cost );
     84                Alternative( Expression *expr, TypeEnvironment &&env, OpenVarSet &&openVars,
     85                        AssertionSet &&need, const Cost &cost, const Cost &cvtCost );
    3186                Alternative( const Alternative &other );
    3287                Alternative &operator=( const Alternative &other );
     
    4499                }
    45100
    46                 Cost cost;
    47                 Cost cvtCost;
    48                 Expression *expr;
    49                 TypeEnvironment env;
     101                /// Sorts by cost
     102                bool operator< ( const Alternative& o ) const { return cost < o.cost; }
     103
     104                Cost cost;            ///< Cost of the whole expression
     105                Cost cvtCost;         ///< Cost of conversions to the satisfying expression
     106                Expression *expr;     ///< Satisfying expression
     107                TypeEnvironment env;  ///< Containing type environment
     108                OpenVarSet openVars;  ///< Open variables for environment
     109                AssertionList need;   ///< Assertions which need to be resolved
    50110        };
    51111
  • src/ResolvExpr/AlternativeFinder.cc

    r07ec1a2 r276a55b2  
    1111// Last Modified By : Peter A. Buhr
    1212// Last Modified On : Thu Nov  1 21:00:56 2018
    13 // Update Count     : 34
     13// Update Count     : 35
    1414//
    1515
     
    3434#include "InitTweak/InitTweak.h"   // for getFunctionName
    3535#include "RenameVars.h"            // for RenameVars, global_renamer
     36#include "ResolveAssertions.h"     // for resolveAssertions
    3637#include "ResolveTypeof.h"         // for resolveTypeof
    3738#include "Resolver.h"              // for resolveStmtExpr
     
    102103                void addAnonConversions( const Alternative & alt );
    103104                /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
    104                 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name );
     105                template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative &alt, const Cost &newCost, const std::string & name );
    105106                /// Adds alternatives for member expressions where the left side has tuple type
    106                 void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
     107                void addTupleMembers( TupleType *tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member );
    107108                /// Adds alternatives for offsetof expressions, given the base type and name of the member
    108109                template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
     
    113114                template<typename OutputIterator>
    114115                void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out );
    115                 /// Checks if assertion parameters match for a new alternative
     116                /// Sets up parameter inference for an output alternative
    116117                template< typename OutputIterator >
    117                 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
     118                void inferParameters( Alternative &newAlt, OutputIterator out );
    118119        private:
    119120                AlternativeFinder & altFinder;
     
    244245        }
    245246
    246         void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) {
     247        void AlternativeFinder::find( Expression *expr, ResolvMode mode ) {
    247248                PassVisitor<Finder> finder( *this );
    248249                expr->accept( finder );
    249                 if ( failFast && alternatives.empty() ) {
     250                if ( mode.failFast && alternatives.empty() ) {
    250251                        PRINT(
    251252                                std::cerr << "No reasonable alternatives for expression " << expr << std::endl;
     
    253254                        SemanticError( expr, "No reasonable alternatives for expression " );
    254255                }
    255                 if ( prune ) {
     256                if ( mode.resolveAssns || mode.prune ) {
     257                        // trim candidates just to those where the assertions resolve
     258                        // - necessary pre-requisite to pruning
     259                        AltList candidates;
     260                        for ( unsigned i = 0; i < alternatives.size(); ++i ) {
     261                                resolveAssertions( alternatives[i], indexer, candidates );
     262                        }
     263                        // fail early if none such
     264                        if ( mode.failFast && candidates.empty() ) {
     265                                std::ostringstream stream;
     266                                stream << "No resolvable alternatives for expression " << expr << "\n"
     267                                       << "Alternatives with failing assertions are:\n";
     268                                printAlts( alternatives, stream, 1 );
     269                                SemanticError( expr->location, stream.str() );
     270                        }
     271                        // reset alternatives
     272                        alternatives = std::move( candidates );
     273                }
     274                if ( mode.prune ) {
    256275                        auto oldsize = alternatives.size();
    257276                        PRINT(
     
    261280                        AltList pruned;
    262281                        pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) );
    263                         if ( failFast && pruned.empty() ) {
     282                        if ( mode.failFast && pruned.empty() ) {
    264283                                std::ostringstream stream;
    265284                                AltList winners;
     
    280299                }
    281300                // adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted
    282                 for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
    283                         if ( adjust ) {
    284                                 adjustExprType( i->expr->get_result(), i->env, indexer );
     301                if ( mode.adjust ) {
     302                        for ( Alternative& i : alternatives ) {
     303                                adjustExprType( i.expr->get_result(), i.env, indexer );
    285304                        }
    286305                }
     
    294313
    295314        void AlternativeFinder::findWithAdjustment( Expression *expr ) {
    296                 find( expr, true );
     315                find( expr, ResolvMode::withAdjustment() );
    297316        }
    298317
    299318        void AlternativeFinder::findWithoutPrune( Expression * expr ) {
    300                 find( expr, true, false );
     319                find( expr, ResolvMode::withoutPrune() );
    301320        }
    302321
    303322        void AlternativeFinder::maybeFind( Expression * expr ) {
    304                 find( expr, true, true, false );
     323                find( expr, ResolvMode::withoutFailFast() );
    305324        }
    306325
     
    317336
    318337                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
    319                         addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
     338                        addAggMembers( structInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
    320339                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
    321                         addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
     340                        addAggMembers( unionInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
    322341                } // if
    323342        }
    324343
    325344        template< typename StructOrUnionType >
    326         void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) {
     345        void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative& alt, const Cost &newCost, const std::string & name ) {
    327346                std::list< Declaration* > members;
    328347                aggInst->lookup( name, members );
     
    332351                                // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    333352                                // can't construct in place and use vector::back
    334                                 Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost );
     353                                Alternative newAlt{ alt, new MemberExpr{ dwt, expr->clone() }, newCost };
    335354                                renameTypes( newAlt.expr );
    336355                                addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
     
    342361        }
    343362
    344         void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
     363        void AlternativeFinder::Finder::addTupleMembers( TupleType *tupleType, Expression *expr,                        const Alternative &alt, const Cost &newCost, Expression *member ) {
    345364                if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
    346365                        // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
     
    348367                        std::string tmp;
    349368                        if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    350                                 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
     369                                alternatives.push_back( Alternative{
     370                                        alt, new TupleIndexExpr( expr->clone(), val ), newCost } );
    351371                        } // if
    352372                } // if
     
    354374
    355375        void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) {
    356                 alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) );
     376                alternatives.push_back( Alternative{ applicationExpr->clone(), env } );
    357377        }
    358378
     
    410430        Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
    411431                ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( alt.expr );
    412                 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    413                 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() );
     432                PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result );
     433                FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base );
    414434
    415435                Cost convCost = Cost::zero;
    416                 std::list< DeclarationWithType* >& formals = function->get_parameters();
     436                std::list< DeclarationWithType* >& formals = function->parameters;
    417437                std::list< DeclarationWithType* >::iterator formal = formals.begin();
    418                 std::list< Expression* >& actuals = appExpr->get_args();
    419 
    420                 for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
    421                         Type * actualType = (*actualExpr)->get_result();
     438                std::list< Expression* >& actuals = appExpr->args;
     439
     440                for ( Expression*& actualExpr : actuals ) {
     441                        Type * actualType = actualExpr->result;
    422442                        PRINT(
    423443                                std::cerr << "actual expression:" << std::endl;
    424                                 (*actualExpr)->print( std::cerr, 8 );
     444                                actualExpr->print( std::cerr, 8 );
    425445                                std::cerr << "--- results are" << std::endl;
    426446                                actualType->print( std::cerr, 8 );
    427447                        )
    428448                        if ( formal == formals.end() ) {
    429                                 if ( function->get_isVarArgs() ) {
     449                                if ( function->isVarArgs ) {
    430450                                        convCost.incUnsafe();
    431451                                        PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; )
    432452                                        // convert reference-typed expressions to value-typed expressions
    433                                         referenceToRvalueConversion( *actualExpr, convCost );
     453                                        referenceToRvalueConversion( actualExpr, convCost );
    434454                                        continue;
    435455                                } else {
     
    437457                                }
    438458                        }
    439                         if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) {
     459                        if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( actualExpr ) ) {
    440460                                // default arguments should be free - don't include conversion cost.
    441461                                // Unwrap them here because they are not relevant to the rest of the system.
    442                                 *actualExpr = def->expr;
     462                                actualExpr = def->expr;
    443463                                ++formal;
    444464                                continue;
    445465                        }
     466                        // mark conversion cost to formal and also specialization cost of formal type
    446467                        Type * formalType = (*formal)->get_type();
    447                         convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env );
     468                        convCost += computeExpressionConversionCost( actualExpr, formalType, indexer, alt.env );
     469                        convCost.decSpec( specCost( formalType ) );
    448470                        ++formal; // can't be in for-loop update because of the continue
    449471                }
     
    452474                }
    453475
    454                 for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) {
     476                // mark specialization cost of return types
     477                for ( DeclarationWithType* returnVal : function->returnVals ) {
     478                        convCost.decSpec( specCost( returnVal->get_type() ) );
     479                }
     480
     481                // mark type variable and specialization cost of forall clause
     482                convCost.incVar( function->forall.size() );
     483                for ( TypeDecl* td : function->forall ) {
     484                        convCost.decSpec( td->assertions.size() );
     485                }
     486
     487                // xxx -- replace with new costs in resolver
     488                for ( InferredParams::const_iterator assert = appExpr->inferParams.begin(); assert != appExpr->inferParams.end(); ++assert ) {
    455489                        convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env );
    456490                }
     
    466500                                needAssertions[ *assert ].isUsed = true;
    467501                        }
    468 ///     needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() );
    469                 }
    470         }
    471 
    472         static const int recursionLimit = /*10*/ 4;  ///< Limit to depth of recursion satisfaction
    473 
    474         void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) {
    475                 for ( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i ) {
    476                         if ( i->second.isUsed ) {
    477                                 indexer.addId( i->first );
    478                         }
    479                 }
    480         }
    481 
    482         template< typename ForwardIterator, typename OutputIterator >
    483         void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, int level, const SymTab::Indexer &indexer, OutputIterator out ) {
    484                 if ( newAlt.cost == Cost::infinity ) return; // don't proceed down this dead end
    485                 if ( begin == end ) {
    486                         if ( newNeed.empty() ) {
    487                                 PRINT(
    488                                         std::cerr << "all assertions satisfied, output alternative: ";
    489                                         newAlt.print( std::cerr );
    490                                         std::cerr << std::endl;
    491                                 );
    492                                 *out++ = newAlt;
    493                                 return;
    494                         } else if ( level >= recursionLimit ) {
    495                                 SemanticError( newAlt.expr->location, "Too many recursive assertions" );
    496                         } else {
    497                                 AssertionSet newerNeed;
    498                                 PRINT(
    499                                         std::cerr << "recursing with new set:" << std::endl;
    500                                         printAssertionSet( newNeed, std::cerr, 8 );
    501                                 )
    502                                 inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out );
    503                                 return;
    504                         }
    505                 }
    506 
    507                 ForwardIterator cur = begin++;
    508                 if ( ! cur->second.isUsed ) {
    509                         inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out );
    510                         return; // xxx - should this continue? previously this wasn't here, and it looks like it should be
    511                 }
    512                 DeclarationWithType *curDecl = cur->first;
    513 
    514                 PRINT(
    515                         std::cerr << "inferRecursive: assertion is ";
    516                         curDecl->print( std::cerr );
    517                         std::cerr << std::endl;
    518                 )
    519                 std::list< SymTab::Indexer::IdData > candidates;
    520                 decls.lookupId( curDecl->get_name(), candidates );
    521 ///   if ( candidates.empty() ) { std::cerr << "no candidates!" << std::endl; }
    522                 for ( const auto & data : candidates ) {
    523                         DeclarationWithType * candidate = data.id;
    524                         PRINT(
    525                                 std::cerr << "inferRecursive: candidate is ";
    526                                 candidate->print( std::cerr );
    527                                 std::cerr << std::endl;
    528                         )
    529 
    530                         AssertionSet newHave, newerNeed( newNeed );
    531                         TypeEnvironment newEnv( newAlt.env );
    532                         OpenVarSet newOpenVars( openVars );
    533                         Type *adjType = candidate->get_type()->clone();
    534                         adjustExprType( adjType, newEnv, indexer );
    535                         renameTyVars( adjType );
    536                         PRINT(
    537                                 std::cerr << "unifying ";
    538                                 curDecl->get_type()->print( std::cerr );
    539                                 std::cerr << " with ";
    540                                 adjType->print( std::cerr );
    541                                 std::cerr << std::endl;
    542                         )
    543                         if ( unify( curDecl->get_type(), adjType, newEnv, newerNeed, newHave, newOpenVars, indexer ) ) {
    544                                 PRINT(
    545                                         std::cerr << "success!" << std::endl;
    546                                 )
    547                                 SymTab::Indexer newDecls( decls );
    548                                 addToIndexer( newHave, newDecls );
    549                                 Alternative newerAlt( newAlt );
    550                                 newerAlt.env = newEnv;
    551                                 assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
    552 
    553                                 // everything with an empty idChain was pulled in by the current assertion.
    554                                 // add current assertion's idChain + current assertion's ID so that the correct inferParameters can be found.
    555                                 for ( auto & a : newerNeed ) {
    556                                         if ( a.second.idChain.empty() ) {
    557                                                 a.second.idChain = cur->second.idChain;
    558                                                 a.second.idChain.push_back( curDecl->get_uniqueId() );
    559                                         }
    560                                 }
    561 
    562                                 Expression *varExpr = data.combine( newerAlt.cvtCost );
    563                                 delete varExpr->get_result();
    564                                 varExpr->set_result( adjType->clone() );
    565                                 PRINT(
    566                                         std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " ";
    567                                         curDecl->print( std::cerr );
    568                                         std::cerr << " with declaration " << candidate->get_uniqueId() << " ";
    569                                         candidate->print( std::cerr );
    570                                         std::cerr << std::endl;
    571                                 )
    572                                 // follow the current assertion's ID chain to find the correct set of inferred parameters to add the candidate to (i.e. the set of inferred parameters belonging to the entity which requested the assertion parameter).
    573                                 InferredParams * inferParameters = &newerAlt.expr->get_inferParams();
    574                                 for ( UniqueId id : cur->second.idChain ) {
    575                                         inferParameters = (*inferParameters)[ id ].inferParams.get();
    576                                 }
    577                                 // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions
    578                                 (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );
    579                                 inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out );
    580                         } else {
    581                                 delete adjType;
    582                         }
    583                 }
    584         }
     502                }
     503        }
     504
     505        /// Unique identifier for matching expression resolutions to their requesting expression
     506        UniqueId globalResnSlot = 0;
    585507
    586508        template< typename OutputIterator >
    587         void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {
    588 //      PRINT(
    589 //          std::cerr << "inferParameters: assertions needed are" << std::endl;
    590 //          printAll( need, std::cerr, 8 );
    591 //          )
    592                 SymTab::Indexer decls( indexer );
    593                 // PRINT(
    594                 //      std::cerr << "============= original indexer" << std::endl;
    595                 //      indexer.print( std::cerr );
    596                 //      std::cerr << "============= new indexer" << std::endl;
    597                 //      decls.print( std::cerr );
    598                 // )
    599                 addToIndexer( have, decls );
    600                 AssertionSet newNeed;
    601                 PRINT(
    602                         std::cerr << "env is: " << std::endl;
    603                         newAlt.env.print( std::cerr, 0 );
    604                         std::cerr << std::endl;
    605                 )
    606 
    607                 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out );
    608 //      PRINT(
    609 //          std::cerr << "declaration 14 is ";
    610 //          Declaration::declFromId
    611 //          *out++ = newAlt;
    612 //          )
     509        void AlternativeFinder::Finder::inferParameters( Alternative &newAlt, OutputIterator out ) {
     510                // Set need bindings for any unbound assertions
     511                UniqueId crntResnSlot = 0;  // matching ID for this expression's assertions
     512                for ( auto& assn : newAlt.need ) {
     513                        // skip already-matched assertions
     514                        if ( assn.info.resnSlot != 0 ) continue;
     515                        // assign slot for expression if needed
     516                        if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; }
     517                        // fix slot to assertion
     518                        assn.info.resnSlot = crntResnSlot;
     519                }
     520                // pair slot to expression
     521                if ( crntResnSlot != 0 ) { newAlt.expr->resnSlots.push_back( crntResnSlot ); }
     522
     523                // add to output list, assertion resolution is deferred
     524                *out++ = newAlt;
    613525        }
    614526
     
    951863                }
    952864                // build and validate new alternative
    953                 Alternative newAlt( appExpr, result.env, cost );
     865                Alternative newAlt{ appExpr, result.env, result.openVars, result.need, cost };
    954866                PRINT(
    955867                        std::cerr << "instantiate function success: " << appExpr << std::endl;
     
    957869                        printAssertionSet( result.need, std::cerr, 8 );
    958870                )
    959                 inferParameters( result.need, result.have, newAlt, result.openVars, out );
     871                inferParameters( newAlt, out );
    960872        }
    961873
     
    12021114
    12031115                // function may return struct or union value, in which case we need to add alternatives
    1204                 // for implicitconversions to each of the anonymous members, must happen after findMinCost
     1116                // for implicit conversions to each of the anonymous members, must happen after findMinCost
    12051117                // since anon conversions are never the cheapest expression
    12061118                for ( const Alternative & alt : winners ) {
     
    12341146                        if ( isLvalue( alt.expr ) ) {
    12351147                                alternatives.push_back(
    1236                                         Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } );
     1148                                        Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } );
    12371149                        } // if
    12381150                } // for
     
    12401152
    12411153        void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) {
    1242                 alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } );
     1154                alternatives.push_back( Alternative{ expr->clone(), env } );
    12431155        }
    12441156
     
    12851197                AltList candidates;
    12861198                for ( Alternative & alt : finder.alternatives ) {
    1287                         AssertionSet needAssertions, haveAssertions;
    1288                         OpenVarSet openVars;
     1199                        AssertionSet needAssertions( alt.need.begin(), alt.need.end() );
     1200                        AssertionSet haveAssertions;
     1201                        OpenVarSet openVars{ alt.openVars };
    12891202
    12901203                        alt.env.extractOpenVars( openVars );
     
    13141227                                // count one safe conversion for each value that is thrown away
    13151228                                thisCost.incSafe( discardedValues );
    1316                                 Alternative newAlt( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env,
    1317                                         alt.cost, thisCost );
    1318                                 inferParameters( needAssertions, haveAssertions, newAlt, openVars,
    1319                                         back_inserter( candidates ) );
     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 ) );
    13201233                        } // if
    13211234                } // for
     
    13301243
    13311244        void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) {
    1332                 assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." );
     1245                assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." );
    13331246                AlternativeFinder finder( indexer, env );
    13341247                // don't prune here, since it's guaranteed all alternatives will have the same type
    13351248                finder.findWithoutPrune( castExpr->get_arg() );
    13361249                for ( Alternative & alt : finder.alternatives ) {
    1337                         alternatives.push_back( Alternative(
    1338                                 new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ),
    1339                                 alt.env, alt.cost ) );
     1250                        alternatives.push_back( Alternative{
     1251                                alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() },
     1252                                alt.cost } );
    13401253                }
    13411254        }
     
    13651278                        // find member of the given type
    13661279                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    1367                                 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
     1280                                addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
    13681281                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    1369                                 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
     1282                                addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
    13701283                        } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
    1371                                 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );
     1284                                addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() );
    13721285                        } // if
    13731286                } // for
     
    13751288
    13761289        void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) {
    1377                 alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) );
     1290                alternatives.push_back( Alternative{ memberExpr->clone(), env } );
    13781291        }
    13791292
     
    13881301                        // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    13891302                        // can't construct in place and use vector::back
    1390                         Alternative newAlt( newExpr, env, Cost::zero, cost );
     1303                        Alternative newAlt{ newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost };
    13911304                        PRINT(
    13921305                                std::cerr << "decl is ";
     
    14061319                // not sufficient to clone here, because variable's type may have changed
    14071320                // since the VariableExpr was originally created.
    1408                 alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) );
     1321                alternatives.push_back( Alternative{ new VariableExpr{ variableExpr->var }, env } );
    14091322        }
    14101323
    14111324        void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) {
    1412                 alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) );
     1325                alternatives.push_back( Alternative{ constantExpr->clone(), env } );
    14131326        }
    14141327
     
    14161329                if ( sizeofExpr->get_isType() ) {
    14171330                        Type * newType = sizeofExpr->get_type()->clone();
    1418                         alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
     1331                        alternatives.push_back( Alternative{
     1332                                new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } );
    14191333                } else {
    14201334                        // find all alternatives for the argument to sizeof
     
    14301344                        Alternative &choice = winners.front();
    14311345                        referenceToRvalueConversion( choice.expr, choice.cost );
    1432                         alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
     1346                        alternatives.push_back( Alternative{
     1347                                choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } );
    14331348                } // if
    14341349        }
     
    14371352                if ( alignofExpr->get_isType() ) {
    14381353                        Type * newType = alignofExpr->get_type()->clone();
    1439                         alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
     1354                        alternatives.push_back( Alternative{
     1355                                new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } );
    14401356                } else {
    14411357                        // find all alternatives for the argument to sizeof
     
    14511367                        Alternative &choice = winners.front();
    14521368                        referenceToRvalueConversion( choice.expr, choice.cost );
    1453                         alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
     1369                        alternatives.push_back( Alternative{
     1370                                choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } );
    14541371                } // if
    14551372        }
     
    14611378                for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    14621379                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
    1463                                 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) );
     1380                                alternatives.push_back( Alternative{
     1381                                        new OffsetofExpr{ aggInst->clone(), dwt }, env } );
    14641382                                renameTypes( alternatives.back().expr );
    14651383                        } else {
     
    14801398
    14811399        void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) {
    1482                 alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) );
     1400                alternatives.push_back( Alternative{ offsetofExpr->clone(), env } );
    14831401        }
    14841402
    14851403        void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) {
    1486                 alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) );
     1404                alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } );
    14871405        }
    14881406
     
    15041422                                Cost cost = Cost::zero;
    15051423                                Expression * newExpr = data.combine( cost );
    1506                                 alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) );
     1424                                alternatives.push_back( Alternative{
     1425                                        new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{},
     1426                                        AssertionList{}, Cost::zero, cost } );
    15071427                                for ( DeclarationWithType * retVal : function->returnVals ) {
    15081428                                        alternatives.back().expr->result = retVal->get_type()->clone();
     
    15431463                                Cost cost = Cost::zero;
    15441464                                Expression * newExpr = data.combine( cost );
    1545                                 alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) );
     1465                                alternatives.push_back( Alternative{
     1466                                        newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost } );
    15461467                                renameTypes( alternatives.back().expr );
    15471468                        } // for
     
    15581479                for ( const Alternative & first : firstFinder.alternatives ) {
    15591480                        for ( const Alternative & second : secondFinder.alternatives ) {
    1560                                 TypeEnvironment compositeEnv;
    1561                                 compositeEnv.simpleCombine( first.env );
     1481                                TypeEnvironment compositeEnv{ first.env };
    15621482                                compositeEnv.simpleCombine( second.env );
    1563 
    1564                                 LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() );
    1565                                 alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) );
     1483                                OpenVarSet openVars{ first.openVars };
     1484                                mergeOpenVars( openVars, second.openVars );
     1485                                AssertionSet need;
     1486                                cloneAll( first.need, need );
     1487                                cloneAll( second.need, need );
     1488
     1489                                LogicalExpr *newExpr = new LogicalExpr{
     1490                                        first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() };
     1491                                alternatives.push_back( Alternative{
     1492                                        newExpr, std::move(compositeEnv), std::move(openVars),
     1493                                        AssertionList( need.begin(), need.end() ), first.cost + second.cost } );
    15661494                        }
    15671495                }
     
    15841512                        for ( const Alternative & second : secondFinder.alternatives ) {
    15851513                                for ( const Alternative & third : thirdFinder.alternatives ) {
    1586                                         TypeEnvironment compositeEnv;
    1587                                         compositeEnv.simpleCombine( first.env );
     1514                                        TypeEnvironment compositeEnv{ first.env };
    15881515                                        compositeEnv.simpleCombine( second.env );
    15891516                                        compositeEnv.simpleCombine( third.env );
    1590 
     1517                                        OpenVarSet openVars{ first.openVars };
     1518                                        mergeOpenVars( openVars, second.openVars );
     1519                                        mergeOpenVars( openVars, third.openVars );
     1520                                        AssertionSet need;
     1521                                        cloneAll( first.need, need );
     1522                                        cloneAll( second.need, need );
     1523                                        cloneAll( third.need, need );
     1524                                        AssertionSet have;
     1525                                       
    15911526                                        // 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 );
    15951527                                        Type* commonType = nullptr;
    1596                                         if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    1597                                                 ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() );
     1528                                        if ( unify( second.expr->result, third.expr->result, compositeEnv,
     1529                                                        need, have, openVars, indexer, commonType ) ) {
     1530                                                ConditionalExpr *newExpr = new ConditionalExpr{
     1531                                                        first.expr->clone(), second.expr->clone(), third.expr->clone() };
    15981532                                                newExpr->result = commonType ? commonType : second.expr->result->clone();
    15991533                                                // convert both options to the conditional result type
    1600                                                 newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env );
    1601                                                 newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env );
    1602                                                 newAlt.expr = newExpr;
    1603                                                 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
     1534                                                Cost cost = first.cost + second.cost + third.cost;
     1535                                                cost += computeExpressionConversionCost(
     1536                                                        newExpr->arg2, newExpr->result, indexer, compositeEnv );
     1537                                                cost += computeExpressionConversionCost(
     1538                                                        newExpr->arg3, newExpr->result, indexer, compositeEnv );
     1539                                                // output alternative
     1540                                                Alternative newAlt{
     1541                                                        newExpr, std::move(compositeEnv), std::move(openVars),
     1542                                                        AssertionList( need.begin(), need.end() ), cost };
     1543                                                inferParameters( newAlt, back_inserter( alternatives ) );
    16041544                                        } // if
    16051545                                } // for
     
    16141554                secondFinder.findWithAdjustment( commaExpr->get_arg2() );
    16151555                for ( const Alternative & alt : secondFinder.alternatives ) {
    1616                         alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) );
     1556                        alternatives.push_back( Alternative{
     1557                                alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } );
    16171558                } // for
    16181559                delete newFirstArg;
     
    16291570                for ( const Alternative & first : firstFinder.alternatives ) {
    16301571                        for ( const Alternative & second : secondFinder.alternatives ) {
    1631                                 TypeEnvironment compositeEnv;
    1632                                 compositeEnv.simpleCombine( first.env );
     1572                                TypeEnvironment compositeEnv{ first.env };
    16331573                                compositeEnv.simpleCombine( second.env );
    1634                                 OpenVarSet openVars;
    1635                                 AssertionSet needAssertions, haveAssertions;
    1636                                 Alternative newAlt( 0, compositeEnv, first.cost + second.cost );
     1574                                OpenVarSet openVars{ first.openVars };
     1575                                mergeOpenVars( openVars, second.openVars );
     1576                                AssertionSet need;
     1577                                cloneAll( first.need, need );
     1578                                cloneAll( second.need, need );
     1579                                AssertionSet have;
     1580
    16371581                                Type* commonType = nullptr;
    1638                                 if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    1639                                         RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() );
     1582                                if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have,
     1583                                                openVars, indexer, commonType ) ) {
     1584                                        RangeExpr * newExpr =
     1585                                                new RangeExpr{ first.expr->clone(), second.expr->clone() };
    16401586                                        newExpr->result = commonType ? commonType : first.expr->result->clone();
    1641                                         newAlt.expr = newExpr;
    1642                                         inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
     1587                                        Alternative newAlt{
     1588                                                newExpr, std::move(compositeEnv), std::move(openVars),
     1589                                                AssertionList( need.begin(), need.end() ), first.cost + second.cost };
     1590                                        inferParameters( newAlt, back_inserter( alternatives ) );
    16431591                                } // if
    16441592                        } // for
     
    16581606
    16591607                        TypeEnvironment compositeEnv;
    1660                         simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv );
    1661                         alternatives.push_back(
    1662                                 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } );
     1608                        OpenVarSet openVars;
     1609                        AssertionSet need;
     1610                        for ( const Alternative& alt : alts ) {
     1611                                compositeEnv.simpleCombine( alt.env );
     1612                                mergeOpenVars( openVars, alt.openVars );
     1613                                cloneAll( alt.need, need );
     1614                        }
     1615                       
     1616                        alternatives.push_back( Alternative{
     1617                                new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars),
     1618                                AssertionList( need.begin(), need.end() ), sumCost( alts ) } );
    16631619                } // for
    16641620        }
    16651621
    16661622        void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) {
    1667                 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
     1623                alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
    16681624        }
    16691625
    16701626        void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    1671                 alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );
     1627                alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } );
    16721628        }
    16731629
     
    16781634                finder.findWithoutPrune( ctorExpr->get_callExpr() );
    16791635                for ( Alternative & alt : finder.alternatives ) {
    1680                         alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) );
     1636                        alternatives.push_back( Alternative{
     1637                                alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } );
    16811638                }
    16821639        }
    16831640
    16841641        void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) {
    1685                 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
     1642                alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
    16861643        }
    16871644
    16881645        void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) {
    1689                 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) );
     1646                alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } );
    16901647        }
    16911648
     
    16961653                        // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked"
    16971654                        UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() );
    1698                         alternatives.push_back( Alternative( newUnqExpr, alt.env, alt.cost ) );
     1655                        alternatives.push_back( Alternative{ alt, newUnqExpr, alt.cost } );
    16991656                }
    17001657        }
     
    17041661                ResolvExpr::resolveStmtExpr( newStmtExpr, indexer );
    17051662                // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr...
    1706                 alternatives.push_back( Alternative( newStmtExpr, env, Cost::zero ) );
     1663                alternatives.push_back( Alternative{ newStmtExpr, env } );
    17071664        }
    17081665
     
    17261683                        for ( Alternative & alt : finder.get_alternatives() ) {
    17271684                                TypeEnvironment newEnv( alt.env );
    1728                                 AssertionSet needAssertions, haveAssertions;
    1729                                 OpenVarSet openVars;  // find things in env that don't have a "representative type" and claim those are open vars?
     1685                                AssertionSet need;
     1686                                cloneAll( alt.need, need );
     1687                                AssertionSet have;
     1688                                OpenVarSet openVars( alt.openVars ); 
     1689                                // xxx - find things in env that don't have a "representative type" and claim
     1690                                // those are open vars?
    17301691                                PRINT(
    17311692                                        std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
    17321693                                )
    1733                                 // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
    1734                                 // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
    1735                                 // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    1736                                 // to.
     1694                                // It's possible that a cast can throw away some values in a multiply-valued
     1695                                // expression. (An example is a cast-to-void, which casts from one value to
     1696                                // zero.)  Figure out the prefix of the subexpression results that are cast
     1697                                // directly.  The candidate is invalid if it has fewer results than there are
     1698                                // types to cast to.
    17371699                                int discardedValues = alt.expr->result->size() - toType->size();
    17381700                                if ( discardedValues < 0 ) continue;
    1739                                 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    1740                                 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
     1701                                // xxx - may need to go into tuple types and extract relevant types and use
     1702                                // unifyList. Note that currently, this does not allow casting a tuple to an
     1703                                // atomic type (e.g. (int)([1, 2, 3]))
     1704                               
    17411705                                // unification run for side-effects
    1742                                 unify( toType, alt.expr->result, newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type??
     1706                                unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer );
     1707                                // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?
    17431708
    17441709                                Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv );
     
    17461711                                        // count one safe conversion for each value that is thrown away
    17471712                                        thisCost.incSafe( discardedValues );
    1748                                         Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost );
    1749                                         inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
     1713                                        Alternative newAlt{
     1714                                                new InitExpr{
     1715                                                        restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() },
     1716                                                std::move(newEnv), std::move(openVars),
     1717                                                AssertionList( need.begin(), need.end() ), alt.cost, thisCost };
     1718                                        inferParameters( newAlt, back_inserter( candidates ) );
    17501719                                }
    17511720                        }
  • src/ResolvExpr/AlternativeFinder.h

    r07ec1a2 r276a55b2  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:56:12 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jul 26 11:24:00 2017
    13 // Update Count     : 4
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Fri Oct -5 10:01:00 2018
     13// Update Count     : 5
    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
    2627#include "SynTree/Visitor.h"             // for Visitor
    2728#include "SynTree/SynTree.h"             // for Visitor Nodes
     
    6869                }
    6970
    70                 void find( Expression *expr, bool adjust = false, bool prune = true, bool failFast = true );
     71                void find( Expression *expr, ResolvMode mode = ResolvMode{} );
    7172                /// Calls find with the adjust flag set; adjustment turns array and function types into equivalent pointer types
    7273                void findWithAdjustment( Expression *expr );
  • src/ResolvExpr/ConversionCost.cc

    r07ec1a2 r276a55b2  
    2828
    2929namespace ResolvExpr {
    30         const Cost Cost::zero =      Cost(  0,  0,  0,  0 );
    31         const Cost Cost::infinity =  Cost( -1, -1, -1, -1 );
    32         const Cost Cost::unsafe =    Cost(  1,  0,  0,  0 );
    33         const Cost Cost::poly =      Cost(  0,  1,  0,  0 );
    34         const Cost Cost::safe =      Cost(  0,  0,  1,  0 );
    35         const Cost Cost::reference = Cost(  0,  0,  0,  1 );
     30        const Cost Cost::zero =      Cost{  0,  0,  0,  0,  0,  0 };
     31        const Cost Cost::infinity =  Cost{ -1, -1, -1, -1,  1, -1 };
     32        const Cost Cost::unsafe =    Cost{  1,  0,  0,  0,  0,  0 };
     33        const Cost Cost::poly =      Cost{  0,  1,  0,  0,  0,  0 };
     34        const Cost Cost::safe =      Cost{  0,  0,  1,  0,  0,  0 };
     35        const Cost Cost::var =       Cost{  0,  0,  0,  1,  0,  0 };
     36        const Cost Cost::spec =      Cost{  0,  0,  0,  0, -1,  0 };
     37        const Cost Cost::reference = Cost{  0,  0,  0,  0,  0,  1 };
    3638
    3739#if 0
  • src/ResolvExpr/Cost.h

    r07ec1a2 r276a55b2  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 09:39:50 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:35:55 2017
    13 // Update Count     : 5
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Fri Oct 05 14:32:00 2018
     13// Update Count     : 7
    1414//
    1515
     
    2121        class Cost {
    2222          private:
    23                 Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost );
     23                Cost( int unsafeCost, int polyCost, int safeCost, int varCost, int specCost,
     24                        int referenceCost );
    2425
    2526          public:
     
    2728                Cost & incPoly( int inc = 1 );
    2829                Cost & incSafe( int inc = 1 );
     30                Cost & incVar( int inc = 1 );
     31                Cost & decSpec( int inc = 1 );
    2932                Cost & incReference( int inc = 1 );
    3033
     
    3235                int get_polyCost() const { return polyCost; }
    3336                int get_safeCost() const { return safeCost; }
     37                int get_varCost() const { return varCost; }
     38                int get_specCost() const { return specCost; }
    3439                int get_referenceCost() const { return referenceCost; }
    3540
     
    4146                bool operator!=( const Cost &other ) const;
    4247                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;
    4350
    4451                static const Cost zero;
     
    4855                static const Cost poly;
    4956                static const Cost safe;
     57                static const Cost var;
     58                static const Cost spec;
    5059                static const Cost reference;
     60
    5161          private:
    52                 int compare( const Cost &other ) const;
    53 
    54                 int unsafeCost;
    55                 int polyCost;
    56                 int safeCost;
    57                 int referenceCost;
     62                int unsafeCost;     ///< Unsafe (narrowing) conversions
     63                int polyCost;       ///< Count of parameters and return values bound to some poly type
     64                int safeCost;       ///< Safe (widening) conversions
     65                int varCost;        ///< Count of polymorphic type variables
     66                int specCost;       ///< Polymorphic type specializations (type assertions), negative cost
     67                int referenceCost;  ///< reference conversions
    5868        };
    5969
    60         inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ) : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), referenceCost( referenceCost ) {}
     70        inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int varCost, int specCost,
     71                        int referenceCost )
     72                : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), varCost( varCost ),
     73                  specCost( specCost ), referenceCost( referenceCost ) {}
    6174
    6275        inline Cost & Cost::incUnsafe( int inc ) {
     
    7588                if ( *this == infinity ) return *this;
    7689                safeCost += inc;
     90                return *this;
     91        }
     92
     93        inline Cost & Cost::incVar( int inc ) {
     94                if ( *this == infinity ) return *this;
     95                varCost += inc;
     96                return *this;
     97        }
     98
     99        inline Cost& Cost::decSpec( int dec ) {
     100                if ( *this == infinity ) return *this;
     101                specCost -= dec;
    77102                return *this;
    78103        }
     
    86111        inline Cost Cost::operator+( const Cost &other ) const {
    87112                if ( *this == infinity || other == infinity ) return infinity;
    88                 return Cost( unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost, referenceCost + other.referenceCost );
     113                return Cost{
     114                        unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost,
     115                        varCost + other.varCost, specCost + other.specCost,
     116                        referenceCost + other.referenceCost };
    89117        }
    90118
    91119        inline Cost Cost::operator-( const Cost &other ) const {
    92120                if ( *this == infinity || other == infinity ) return infinity;
    93                 return Cost( unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost, referenceCost - other.referenceCost );
     121                return Cost{
     122                        unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost,
     123                        varCost - other.varCost, specCost - other.specCost,
     124                        referenceCost - other.referenceCost };
    94125        }
    95126
     
    103134                polyCost += other.polyCost;
    104135                safeCost += other.safeCost;
     136                varCost += other.varCost;
     137                specCost += other.specCost;
    105138                referenceCost += other.referenceCost;
    106139                return *this;
     
    123156                } else if ( safeCost < other.safeCost ) {
    124157                        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;
    125166                } else if ( referenceCost > other.referenceCost ) {
    126167                        return false;
     
    130171                        return false;
    131172                } // if
     173        }
     174
     175        inline int Cost::compare( const Cost &other ) const {
     176                if ( *this == infinity ) return +1;
     177                if ( other == infinity ) return -1;
     178
     179                int c = unsafeCost - other.unsafeCost; if ( c ) return c;
     180                c = polyCost - other.polyCost; if ( c ) return c;
     181                c = safeCost - other.safeCost; if ( c ) return c;
     182                c = varCost - other.varCost; if ( c ) return c;
     183                c = specCost - other.specCost; if ( c ) return c;
     184                return referenceCost - other.referenceCost;
    132185        }
    133186
     
    136189                        && polyCost == other.polyCost
    137190                        && safeCost == other.safeCost
     191                        && varCost == other.varCost
     192                        && specCost == other.specCost
    138193                        && referenceCost == other.referenceCost;
    139194        }
     
    144199
    145200        inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) {
    146                 os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " << cost.safeCost << ", " << cost.referenceCost << " )";
    147                 return os;
     201                return os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", "
     202                          << cost.safeCost << ", " << cost.varCost << ", " << cost.specCost << ", "
     203                          << cost.referenceCost << " )";
    148204        }
    149205} // namespace ResolvExpr
  • src/ResolvExpr/Resolver.cc

    r07ec1a2 r276a55b2  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Feb 17 11:19:40 2018
    13 // Update Count     : 213
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Fri Oct 05 09:43:00 2018
     13// Update Count     : 214
    1414//
    1515
    16 #include <stddef.h>                      // for NULL
    1716#include <cassert>                       // for strict_dynamic_cast, assert
    1817#include <memory>                        // for allocator, allocator_traits<...
    1918#include <tuple>                         // for get
    20 #include <vector>
     19#include <vector>                        // for vector
    2120
    2221#include "Alternative.h"                 // for Alternative, AltList
     
    3130#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    3231#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, bool adjust = false, bool prune = true, bool failFast = true) {
     170                void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) {
    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;
    172177                        TypeEnvironment env;
    173178                        AlternativeFinder finder( indexer, env );
    174                         finder.find( untyped, adjust, prune, failFast );
     179                        finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
     180                        --recursion_level;
    175181
    176182                        #if 0
     
    185191                        #endif
    186192
     193                        // produce filtered list of alternatives
    187194                        AltList candidates;
    188195                        for ( Alternative & alt : finder.get_alternatives() ) {
     
    192199                        }
    193200
    194                         // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining
    195                         // choose the lowest cost expression among the candidates
     201                        // produce invalid error if no candidates
     202                        if ( candidates.empty() ) {
     203                                SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
     204                        }
     205
     206                        // search for cheapest candidate
    196207                        AltList winners;
    197                         findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
    198                         if ( winners.size() == 0 ) {
    199                                 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
    200                         } else if ( winners.size() != 1 ) {
     208                        bool seen_undeleted = false;
     209                        for ( unsigned i = 0; i < candidates.size(); ++i ) {
     210                                int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost );
     211
     212                                if ( c > 0 ) continue; // skip more expensive than winner
     213
     214                                if ( c < 0 ) {
     215                                        // reset on new cheapest
     216                                        seen_undeleted = ! findDeletedExpr( candidates[i].expr );
     217                                        winners.clear();
     218                                } else /* if ( c == 0 ) */ {
     219                                        if ( findDeletedExpr( candidates[i].expr ) ) {
     220                                                // skip deleted expression if already seen one equivalent-cost not
     221                                                if ( seen_undeleted ) continue;
     222                                        } else if ( ! seen_undeleted ) {
     223                                                // replace list of equivalent-cost deleted expressions with one non-deleted
     224                                                winners.clear();
     225                                                seen_undeleted = true;
     226                                        }
     227                                }
     228
     229                                winners.emplace_back( std::move( candidates[i] ) );
     230                        }
     231
     232                        // promote alternative.cvtCost to .cost
     233                        // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost
     234                        for ( Alternative& winner : winners ) {
     235                                winner.cost = winner.cvtCost;
     236                        }
     237                       
     238                        // produce ambiguous errors, if applicable
     239                        if ( winners.size() != 1 ) {
    201240                                std::ostringstream stream;
    202241                                stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
     
    207246                        }
    208247
    209                         // there is one unambiguous interpretation - move the expression into the with statement
    210                         Alternative & choice = winners.front();
    211                         if ( findDeletedExpr( choice.expr ) ) {
     248                        // single selected choice
     249                        Alternative& choice = winners.front();
     250
     251                        // fail on only expression deleted
     252                        if ( ! seen_undeleted ) {
    212253                                SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
    213254                        }
     255
     256                        // xxx - check for ambiguous expressions
     257                       
     258                        // output selected choice
    214259                        alt = std::move( choice );
    215260                }
    216261
    217262                /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
    218                 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
     263                void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {
    219264                        if ( ! untyped ) return;
    220265                        Alternative choice;
    221                         findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast );
     266                        findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode );
    222267                        finishExpr( choice.expr, choice.env, untyped->env );
    223268                        delete untyped;
     
    250295                untyped.arg = expr;
    251296                Alternative choice;
    252                 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true );
     297                findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() );
    253298                CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
    254299                env = std::move( choice.env );
     
    357402
    358403        void Resolver::previsit( ObjectDecl *objectDecl ) {
    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.
     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.
    364409                GuardValue( currentObject );
    365410                currentObject = CurrentObject( objectDecl->get_type() );
     
    397442
    398443        void Resolver::postvisit( FunctionDecl *functionDecl ) {
    399                 // default value expressions have an environment which shouldn't be there and trips up later passes.
    400                 // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently
    401                 // see how it's useful.
     444                // default value expressions have an environment which shouldn't be there and trips up
     445                // later passes.
     446                // xxx - it might be necessary to somehow keep the information from this environment, but I
     447                // can't currently see how it's useful.
    402448                for ( Declaration * d : functionDecl->type->parameters ) {
    403449                        if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
     
    749795                initExpr->expr = nullptr;
    750796                std::swap( initExpr->env, newExpr->env );
    751                 // InitExpr may have inferParams in the case where the expression specializes a function pointer,
    752                 // and newExpr may already have inferParams of its own, so a simple swap is not sufficient.
     797                // InitExpr may have inferParams in the case where the expression specializes a function
     798                // pointer, and newExpr may already have inferParams of its own, so a simple swap is not
     799                // sufficient.
    753800                newExpr->spliceInferParams( initExpr );
    754801                delete initExpr;
    755802
    756                 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions)
     803                // get the actual object's type (may not exactly match what comes back from the resolver
     804                // due to conversions)
    757805                Type * initContext = currentObject.getCurrentType();
    758806
     
    766814                                        if ( isCharType( pt->get_base() ) ) {
    767815                                                if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) {
    768                                                         // strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
     816                                                        // strip cast if we're initializing a char[] with a char *,
     817                                                        // e.g.  char x[] = "hello";
    769818                                                        newExpr = ce->get_arg();
    770819                                                        ce->set_arg( nullptr );
     
    788837                // move cursor into brace-enclosed initializer-list
    789838                currentObject.enterListInit();
    790                 // xxx - fix this so that the list isn't copied, iterator should be used to change current element
     839                // xxx - fix this so that the list isn't copied, iterator should be used to change current
     840                // element
    791841                std::list<Designation *> newDesignations;
    792842                for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) {
    793                         // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving
    794                         // the initializer against that object.
     843                        // iterate designations and initializers in pairs, moving the cursor to the current
     844                        // designated object and resolving the initializer against that object.
    795845                        Designation * des = std::get<0>(p);
    796846                        Initializer * init = std::get<1>(p);
     
    822872                // fall back on C-style initializer
    823873                delete ctorInit->get_ctor();
    824                 ctorInit->set_ctor( NULL );
     874                ctorInit->set_ctor( nullptr );
    825875                delete ctorInit->get_dtor();
    826                 ctorInit->set_dtor( NULL );
     876                ctorInit->set_dtor( nullptr );
    827877                maybeAccept( ctorInit->get_init(), *visitor );
    828878        }
     
    867917
    868918                // xxx - todo -- what about arrays?
    869                 // if ( dtor == NULL && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
     919                // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
    870920                //      // can reduce the constructor down to a SingleInit using the
    871921                //      // second argument from the ctor call, since
    872922                //      delete ctorInit->get_ctor();
    873                 //      ctorInit->set_ctor( NULL );
     923                //      ctorInit->set_ctor( nullptr );
    874924
    875925                //      Expression * arg =
  • src/ResolvExpr/TypeEnvironment.cc

    r07ec1a2 r276a55b2  
    120120
    121121        const EqvClass* TypeEnvironment::lookup( const std::string &var ) const {
    122                 for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {
     122                for ( ClassList::const_iterator i = env.begin(); i != env.end(); ++i ) {
    123123                        if ( i->vars.find( var ) != i->vars.end() ) return &*i;
    124124                } // for
     
    168168
    169169        void TypeEnvironment::makeSubstitution( TypeSubstitution &sub ) const {
    170                 for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
     170                for ( ClassList::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
    171171                        for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) {
    172172                                if ( theClass->type ) {
     
    188188        }
    189189
    190         std::list< EqvClass >::iterator TypeEnvironment::internal_lookup( const std::string &var ) {
    191                 for ( std::list< EqvClass >::iterator i = env.begin(); i != env.end(); ++i ) {
     190        TypeEnvironment::ClassList::iterator TypeEnvironment::internal_lookup( const std::string &var ) {
     191                for ( ClassList::iterator i = env.begin(); i != env.end(); ++i ) {
    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
    201298        void TypeEnvironment::extractOpenVars( OpenVarSet &openVars ) const {
    202                 for ( std::list< EqvClass >::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) {
     299                for ( ClassList::const_iterator eqvClass = env.begin(); eqvClass != env.end(); ++eqvClass ) {
    203300                        for ( std::set< std::string >::const_iterator var = eqvClass->vars.begin(); var != eqvClass->vars.end(); ++var ) {
    204301                                openVars[ *var ] = eqvClass->data;
  • src/ResolvExpr/TypeEnvironment.h

    r07ec1a2 r276a55b2  
    3939        // declarations.
    4040        //
    41         // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator.
     41        // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this
     42        // comparator.
    4243        //
    4344        // Note: since this compares pointers for position, minor changes in the source file that affect
    4445        // memory layout can alter compilation time in unpredictable ways. For example, the placement
    4546        // of a line directive can reorder type pointers with respect to each other so that assertions
    46         // are seen in different orders, causing a potentially different number of unification calls when
    47         // resolving assertions. I've seen a TU go from 36 seconds to 27 seconds by reordering line directives
    48         // alone, so it would be nice to fix this comparison so that assertions compare more consistently.
    49         // I've tried to modify this to compare on mangle name instead of type as the second comparator, but
    50         // this causes some assertions to never be recorded. More investigation is needed.
     47        // are seen in different orders, causing a potentially different number of unification calls
     48        // when resolving assertions. I've seen a TU go from 36 seconds to 27 seconds by reordering
     49        // line directives alone, so it would be nice to fix this comparison so that assertions compare
     50        // more consistently. I've tried to modify this to compare on mangle name instead of type as
     51        // the second comparator, but this causes some assertions to never be recorded. More
     52        // investigation is needed.
    5153        struct AssertCompare {
    5254                bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const {
     
    5759        };
    5860        struct AssertionSetValue {
    59                 bool isUsed;
    60                 // chain of Unique IDs of the assertion declarations. The first ID in the chain is the ID of an assertion on the current type,
    61                 // with each successive ID being the ID of an assertion pulled in by the previous ID. The last ID in the chain is
    62                 // the ID of the assertion that pulled in the current assertion.
    63                 std::list< UniqueId > idChain;
     61                bool isUsed;        ///< True if assertion needs to be resolved
     62                UniqueId resnSlot;  ///< ID of slot assertion belongs to
     63
     64                AssertionSetValue() : isUsed(false), resnSlot(0) {}
    6465        };
    6566        typedef std::map< DeclarationWithType*, AssertionSetValue, AssertCompare > AssertionSet;
    6667        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        }
    6773
    6874        void printAssertionSet( const AssertionSet &, std::ostream &, int indent = 0 );
     
    9197
    9298        class TypeEnvironment {
     99                using ClassList = std::list< EqvClass >;
    93100          public:
    94101                const EqvClass* lookup( const std::string &var ) const;
     
    103110                bool isEmpty() const { return env.empty(); }
    104111                void print( std::ostream &os, Indenter indent = {} ) const;
    105                 // void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) );
     112               
     113                /// Simply concatenate the second environment onto this one; no safety checks performed
    106114                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               
    107128                void extractOpenVars( OpenVarSet &openVars ) const;
    108129                TypeEnvironment *clone() const { return new TypeEnvironment( *this ); }
     
    123144                void forbidWidening();
    124145
    125                 using iterator = std::list< EqvClass >::const_iterator;
     146                using iterator = ClassList::const_iterator;
    126147                iterator begin() const { return env.begin(); }
    127148                iterator end() const { return env.end(); }
    128149
    129150          private:
    130                 std::list< EqvClass > env;
     151                ClassList env;
    131152               
    132                 std::list< EqvClass >::iterator internal_lookup( const std::string &var );
     153                ClassList::iterator internal_lookup( const std::string &var );
    133154        };
    134155
  • src/ResolvExpr/module.mk

    r07ec1a2 r276a55b2  
    3333       ResolvExpr/TypeEnvironment.cc \
    3434       ResolvExpr/CurrentObject.cc \
    35        ResolvExpr/ExplodedActual.cc
     35       ResolvExpr/ExplodedActual.cc \
     36       ResolvExpr/SpecCost.cc \
     37       ResolvExpr/ResolveAssertions.cc
  • src/ResolvExpr/typeops.h

    r07ec1a2 r276a55b2  
    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
    7478        // in PtrsAssignable.cc
    7579        int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env );
     
    102106        int polyCost( Type *type, const TypeEnvironment &env, const SymTab::Indexer &indexer );
    103107
     108        // in SpecCost.cc
     109        int specCost( Type *type );
     110
    104111        // in Occurs.cc
    105112        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        }
    106122
    107123        // in AlternativeFinder.cc
  • src/SynTree/ApplicationExpr.cc

    r07ec1a2 r276a55b2  
    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

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

    r07ec1a2 r276a55b2  
    2121#include <memory>                 // for allocator, unique_ptr
    2222#include <string>                 // for string
     23#include <vector>                 // for vector
    2324
    2425#include "BaseSyntaxNode.h"       // for BaseSyntaxNode
     
    3839/// but subject to decay-to-pointer and type parameter renaming
    3940struct ParamEntry {
    40         ParamEntry(): decl( 0 ), actualType( 0 ), formalType( 0 ), expr( 0 ), inferParams( new InferredParams ) {}
    41         ParamEntry( UniqueId decl, Type * actualType, Type * formalType, Expression* expr ): decl( decl ), actualType( actualType ), formalType( formalType ), expr( expr ), inferParams( new InferredParams ) {}
     41        ParamEntry(): decl( 0 ), actualType( 0 ), formalType( 0 ), expr( 0 )/*, inferParams( new InferredParams )*/ {}
     42        ParamEntry( UniqueId decl, Type * actualType, Type * formalType, Expression* expr ): decl( decl ), actualType( actualType ), formalType( formalType ), expr( expr )/*, inferParams( new InferredParams )*/ {}
    4243        ParamEntry( const ParamEntry & other );
    4344        ParamEntry( ParamEntry && other );
     
    5051        Type * formalType;
    5152        Expression * expr;
    52         std::unique_ptr< InferredParams > inferParams;
     53        // std::unique_ptr< InferredParams > inferParams;
    5354};
    5455
     
    5960        TypeSubstitution * env;
    6061        bool extension = false;
    61         InferredParams inferParams;
     62        InferredParams inferParams;       ///< Post-resolution inferred parameter slots
     63        std::vector<UniqueId> resnSlots;  ///< Pre-resolution inferred parameter slots
     64       
     65        // xxx - should turn inferParams+resnSlots into a union to save some memory
    6266
    6367        Expression();
     
    7377        bool get_extension() const { return extension; }
    7478        Expression * set_extension( bool exten ) { extension = exten; return this; }
    75 
    76         InferredParams & get_inferParams() { return inferParams; }
    7779
    7880        // move other's inferParams to this
  • src/Tuples/Explode.h

    r07ec1a2 r276a55b2  
    4444        template<typename OutputIterator>
    4545        void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env,
     46                        const ResolvExpr::OpenVarSet& openVars, const ResolvExpr::AssertionList& need,
    4647                        const ResolvExpr::Cost& cost, const ResolvExpr::Cost& cvtCost ) {
    47                 *out++ = ResolvExpr::Alternative{ expr, env, cost, cvtCost };
     48                *out++ = ResolvExpr::Alternative{ expr, env, openVars, need, cost, cvtCost };
    4849        }
    4950
    5051        /// Append alternative to an ExplodedActual
    5152        static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr,
    52                         const ResolvExpr::TypeEnvironment&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
     53                        const ResolvExpr::TypeEnvironment&, const ResolvExpr::OpenVarSet&,
     54                        const ResolvExpr::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
    5355                ea.exprs.emplace_back( expr );
    54                 /// xxx -- merge environment, cost?
     56                /// xxx -- merge environment, openVars, need, cost?
    5557        }
    5658
     
    6870                                        // distribute reference cast over all components
    6971                                        append( std::forward<Output>(out), distributeReference( alt.release_expr() ),
    70                                                 alt.env, alt.cost, alt.cvtCost );
     72                                                alt.env, alt.openVars, alt.need, alt.cost, alt.cvtCost );
    7173                                }
    7274                                // 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)
     
    102104                } else {
    103105                        // atomic (non-tuple) type - output a clone of the expression in a new alternative
    104                         append( std::forward<Output>(out), expr->clone(), alt.env, alt.cost, alt.cvtCost );
     106                        append( std::forward<Output>(out), expr->clone(), alt.env, alt.openVars, alt.need, 
     107                                alt.cost, alt.cvtCost );
    105108                }
    106109        }
  • src/Tuples/TupleAssignment.cc

    r07ec1a2 r276a55b2  
    6262                struct Matcher {
    6363                  public:
    64                         Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const
    65                                 ResolvExpr::AltList& rhs );
     64                        Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,
     65                                const ResolvExpr::AltList& rhs );
    6666                        virtual ~Matcher() {}
     67                       
    6768                        virtual void match( std::list< Expression * > &out ) = 0;
    6869                        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                       
    6981                        ResolvExpr::AltList lhs, rhs;
    7082                        TupleAssignSpotter &spotter;
     
    7284                        std::list< ObjectDecl * > tmpDecls;
    7385                        ResolvExpr::TypeEnvironment compositeEnv;
     86                        ResolvExpr::OpenVarSet openVars;
     87                        ResolvExpr::AssertionSet need;
    7488                };
    7589
     
    245259                }
    246260
    247                 // extract expressions from the assignment alternatives to produce a list of assignments that
    248                 // together form a single alternative
     261                // extract expressions from the assignment alternatives to produce a list of assignments
     262                // that together form a single alternative
    249263                std::list< Expression *> solved_assigns;
    250264                for ( ResolvExpr::Alternative & alt : current ) {
    251265                        solved_assigns.push_back( alt.expr->clone() );
    252                 }
    253                 // combine assignment environments into combined expression environment
    254                 simpleCombineEnvironments( current.begin(), current.end(), matcher->compositeEnv );
     266                        matcher->combineState( alt );
     267                }
     268               
    255269                // xxx -- was push_front
    256                 currentFinder.get_alternatives().push_back( ResolvExpr::Alternative(
    257                         new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv,
    258                         ResolvExpr::sumCost( current ) + matcher->baseCost ) );
     270                currentFinder.get_alternatives().push_back( ResolvExpr::Alternative{
     271                        new TupleAssignExpr{ solved_assigns, matcher->tmpDecls }, matcher->compositeEnv,
     272                        matcher->openVars,
     273                        ResolvExpr::AssertionList( matcher->need.begin(), matcher->need.end() ),
     274                        ResolvExpr::sumCost( current ) + matcher->baseCost } );
    259275        }
    260276
     
    263279        : lhs(lhs), rhs(rhs), spotter(spotter),
    264280          baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) {
    265                 simpleCombineEnvironments( lhs.begin(), lhs.end(), compositeEnv );
    266                 simpleCombineEnvironments( rhs.begin(), rhs.end(), compositeEnv );
     281                combineState( lhs );
     282                combineState( rhs );
    267283        }
    268284
  • tests/.expect/castError.txt

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

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