Ignore:
Timestamp:
Oct 29, 2019, 4:01:24 PM (6 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
773db65, 9421f3d8
Parents:
7951100 (diff), 8364209 (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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sat May 16 23:52:08 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Feb 17 11:19:39 2018
    13 // Update Count     : 33
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Aug  8 16:35:00 2019
     13// Update Count     : 38
    1414//
    1515
     
    2525#include <vector>                  // for vector
    2626
     27#include "CompilationState.h"      // for resolvep
    2728#include "Alternative.h"           // for AltList, Alternative
    2829#include "AlternativeFinder.h"
     30#include "AST/Expr.hpp"
     31#include "AST/SymbolTable.hpp"
     32#include "AST/Type.hpp"
    2933#include "Common/SemanticError.h"  // for SemanticError
    3034#include "Common/utility.h"        // for deleteAll, printAll, CodeLocation
     
    3337#include "InitTweak/InitTweak.h"   // for getFunctionName
    3438#include "RenameVars.h"            // for RenameVars, global_renamer
     39#include "ResolveAssertions.h"     // for resolveAssertions
    3540#include "ResolveTypeof.h"         // for resolveTypeof
    3641#include "Resolver.h"              // for resolveStmtExpr
     
    4954#include "typeops.h"               // for adjustExprType, polyCost, castCost
    5055
    51 extern bool resolvep;
    5256#define PRINT( text ) if ( resolvep ) { text }
    5357//#define DEBUG_COST
    54 
    55 using std::move;
    56 
    57 /// copies any copyable type
    58 template<typename T>
    59 T copy(const T& x) { return x; }
    6058
    6159namespace ResolvExpr {
     
    8179                void postvisit( OffsetofExpr * offsetofExpr );
    8280                void postvisit( OffsetPackExpr * offsetPackExpr );
    83                 void postvisit( AttrExpr * attrExpr );
    8481                void postvisit( LogicalExpr * logicalExpr );
    8582                void postvisit( ConditionalExpr * conditionalExpr );
     
    10299                void addAnonConversions( const Alternative & alt );
    103100                /// 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 );
     101                template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative &alt, const Cost &newCost, const std::string & name );
    105102                /// 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 );
     103                void addTupleMembers( TupleType *tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member );
    107104                /// Adds alternatives for offsetof expressions, given the base type and name of the member
    108105                template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
     
    112109                /// Finds matching alternatives for a function, given a set of arguments
    113110                template<typename OutputIterator>
    114                 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out );
    115                 /// Checks if assertion parameters match for a new alternative
     111                void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs_old& args, OutputIterator out );
     112                /// Sets up parameter inference for an output alternative
    116113                template< typename OutputIterator >
    117                 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
     114                void inferParameters( Alternative &newAlt, OutputIterator out );
    118115        private:
    119116                AlternativeFinder & altFinder;
     
    133130
    134131        void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt ) {
    135                 Indenter indent = { Indenter::tabsize, indentAmt };
     132                Indenter indent = { indentAmt };
    136133                for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
    137134                        i->print( os, indent );
     
    176173                                                selected[ mangleName ] = current;
    177174                                        } else if ( candidate->cost == mapPlace->second.candidate->cost ) {
    178                                                 PRINT(
    179                                                         std::cerr << "marking ambiguous" << std::endl;
    180                                                 )
    181                                                 mapPlace->second.isAmbiguous = true;
     175                                                // if one of the candidates contains a deleted identifier, can pick the other, since
     176                                                // deleted expressions should not be ambiguous if there is another option that is at least as good
     177                                                if ( findDeletedExpr( candidate->expr ) ) {
     178                                                        // do nothing
     179                                                        PRINT( std::cerr << "candidate is deleted" << std::endl; )
     180                                                } else if ( findDeletedExpr( mapPlace->second.candidate->expr ) ) {
     181                                                        PRINT( std::cerr << "current is deleted" << std::endl; )
     182                                                        selected[ mangleName ] = current;
     183                                                } else {
     184                                                        PRINT(
     185                                                                std::cerr << "marking ambiguous" << std::endl;
     186                                                        )
     187                                                        mapPlace->second.isAmbiguous = true;
     188                                                }
    182189                                        } else {
    183190                                                PRINT(
     
    234241        }
    235242
    236         void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) {
     243        void AlternativeFinder::find( Expression *expr, ResolvMode mode ) {
    237244                PassVisitor<Finder> finder( *this );
    238245                expr->accept( finder );
    239                 if ( failFast && alternatives.empty() ) {
     246                if ( mode.failFast && alternatives.empty() ) {
    240247                        PRINT(
    241248                                std::cerr << "No reasonable alternatives for expression " << expr << std::endl;
     
    243250                        SemanticError( expr, "No reasonable alternatives for expression " );
    244251                }
    245                 if ( prune ) {
     252                if ( mode.satisfyAssns || mode.prune ) {
     253                        // trim candidates just to those where the assertions resolve
     254                        // - necessary pre-requisite to pruning
     255                        AltList candidates;
     256                        std::list<std::string> errors;
     257                        for ( unsigned i = 0; i < alternatives.size(); ++i ) {
     258                                resolveAssertions( alternatives[i], indexer, candidates, errors );
     259                        }
     260                        // fail early if none such
     261                        if ( mode.failFast && candidates.empty() ) {
     262                                std::ostringstream stream;
     263                                stream << "No alternatives with satisfiable assertions for " << expr << "\n";
     264                                //        << "Alternatives with failing assertions are:\n";
     265                                // printAlts( alternatives, stream, 1 );
     266                                for ( const auto& err : errors ) {
     267                                        stream << err;
     268                                }
     269                                SemanticError( expr->location, stream.str() );
     270                        }
     271                        // reset alternatives
     272                        alternatives = std::move( candidates );
     273                }
     274                if ( mode.prune ) {
    246275                        auto oldsize = alternatives.size();
    247276                        PRINT(
     
    251280                        AltList pruned;
    252281                        pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) );
    253                         if ( failFast && pruned.empty() ) {
     282                        if ( mode.failFast && pruned.empty() ) {
    254283                                std::ostringstream stream;
    255284                                AltList winners;
     
    270299                }
    271300                // adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted
    272                 for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
    273                         if ( adjust ) {
    274                                 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 );
    275304                        }
    276305                }
     
    284313
    285314        void AlternativeFinder::findWithAdjustment( Expression *expr ) {
    286                 find( expr, true );
     315                find( expr, ResolvMode::withAdjustment() );
    287316        }
    288317
    289318        void AlternativeFinder::findWithoutPrune( Expression * expr ) {
    290                 find( expr, true, false );
     319                find( expr, ResolvMode::withoutPrune() );
    291320        }
    292321
    293322        void AlternativeFinder::maybeFind( Expression * expr ) {
    294                 find( expr, true, true, false );
     323                find( expr, ResolvMode::withoutFailFast() );
    295324        }
    296325
     
    306335                }
    307336
    308                 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
    309                         addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
    310                 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
    311                         addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
     337                if ( StructInstType * structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
     338                        addAggMembers( structInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
     339                } else if ( UnionInstType * unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
     340                        addAggMembers( unionInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
    312341                } // if
    313342        }
    314343
    315344        template< typename StructOrUnionType >
    316         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 ) {
    317346                std::list< Declaration* > members;
    318347                aggInst->lookup( name, members );
    319348
    320349                for ( Declaration * decl : members ) {
    321                         if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
     350                        if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
    322351                                // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    323352                                // can't construct in place and use vector::back
    324                                 Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost );
     353                                Alternative newAlt{ alt, new MemberExpr{ dwt, expr->clone() }, newCost };
    325354                                renameTypes( newAlt.expr );
    326355                                addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
     
    332361        }
    333362
    334         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 ) {
    335364                if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
    336365                        // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
    337                         // xxx - this should be improved by memoizing the value of constant exprs
    338                         // during parsing and reusing that information here.
    339                         std::stringstream ss( constantExpr->get_constant()->get_value() );
    340                         int val = 0;
     366                        auto val = constantExpr->intValue();
    341367                        std::string tmp;
    342                         if ( ss >> val && ! (ss >> tmp) ) {
    343                                 if ( val >= 0 && (unsigned int)val < tupleType->size() ) {
    344                                         alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
    345                                 } // if
     368                        if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
     369                                alternatives.push_back( Alternative{
     370                                        alt, new TupleIndexExpr( expr->clone(), val ), newCost } );
    346371                        } // if
    347                 } else if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) {
    348                         // xxx - temporary hack until 0/1 are int constants
    349                         if ( nameExpr->get_name() == "0" || nameExpr->get_name() == "1" ) {
    350                                 std::stringstream ss( nameExpr->get_name() );
    351                                 int val;
    352                                 ss >> val;
    353                                 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
    354                         }
    355372                } // if
    356373        }
    357374
    358         void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) {
    359                 alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) );
    360         }
    361 
    362         Cost computeConversionCost( Type * actualType, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) {
     375        void AlternativeFinder::Finder::postvisit( ApplicationExpr * applicationExpr ) {
     376                alternatives.push_back( Alternative{ applicationExpr->clone(), env } );
     377        }
     378
     379        Cost computeConversionCost( Type * actualType, Type * formalType, bool actualIsLvalue,
     380                        const SymTab::Indexer &indexer, const TypeEnvironment & env ) {
    363381                PRINT(
    364382                        std::cerr << std::endl << "converting ";
     
    370388                        std::cerr << std::endl;
    371389                )
    372                 Cost convCost = conversionCost( actualType, formalType, indexer, env );
     390                Cost convCost = conversionCost( actualType, formalType, actualIsLvalue, indexer, env );
    373391                PRINT(
    374392                        std::cerr << std::endl << "cost is " << convCost << std::endl;
     
    385403
    386404        Cost computeExpressionConversionCost( Expression *& actualExpr, Type * formalType, const SymTab::Indexer &indexer, const TypeEnvironment & env ) {
    387                 Cost convCost = computeConversionCost( actualExpr->result, formalType, indexer, env );
     405                Cost convCost = computeConversionCost(
     406                        actualExpr->result, formalType, actualExpr->get_lvalue(), indexer, env );
    388407
    389408                // if there is a non-zero conversion cost, ignoring poly cost, then the expression requires conversion.
     
    413432        Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
    414433                ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( alt.expr );
    415                 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    416                 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() );
     434                PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result );
     435                FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base );
    417436
    418437                Cost convCost = Cost::zero;
    419                 std::list< DeclarationWithType* >& formals = function->get_parameters();
     438                std::list< DeclarationWithType* >& formals = function->parameters;
    420439                std::list< DeclarationWithType* >::iterator formal = formals.begin();
    421                 std::list< Expression* >& actuals = appExpr->get_args();
    422 
    423                 for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
    424                         Type * actualType = (*actualExpr)->get_result();
     440                std::list< Expression* >& actuals = appExpr->args;
     441
     442                for ( Expression*& actualExpr : actuals ) {
     443                        Type * actualType = actualExpr->result;
    425444                        PRINT(
    426445                                std::cerr << "actual expression:" << std::endl;
    427                                 (*actualExpr)->print( std::cerr, 8 );
     446                                actualExpr->print( std::cerr, 8 );
    428447                                std::cerr << "--- results are" << std::endl;
    429448                                actualType->print( std::cerr, 8 );
    430449                        )
    431450                        if ( formal == formals.end() ) {
    432                                 if ( function->get_isVarArgs() ) {
     451                                if ( function->isVarArgs ) {
    433452                                        convCost.incUnsafe();
    434453                                        PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; )
    435454                                        // convert reference-typed expressions to value-typed expressions
    436                                         referenceToRvalueConversion( *actualExpr, convCost );
     455                                        referenceToRvalueConversion( actualExpr, convCost );
    437456                                        continue;
    438457                                } else {
     
    440459                                }
    441460                        }
     461                        if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( actualExpr ) ) {
     462                                // default arguments should be free - don't include conversion cost.
     463                                // Unwrap them here because they are not relevant to the rest of the system.
     464                                actualExpr = def->expr;
     465                                ++formal;
     466                                continue;
     467                        }
     468                        // mark conversion cost to formal and also specialization cost of formal type
    442469                        Type * formalType = (*formal)->get_type();
    443                         convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env );
     470                        convCost += computeExpressionConversionCost( actualExpr, formalType, indexer, alt.env );
     471                        convCost.decSpec( specCost( formalType ) );
    444472                        ++formal; // can't be in for-loop update because of the continue
    445473                }
     
    448476                }
    449477
    450                 for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) {
    451                         convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env );
     478                // specialization cost of return types can't be accounted for directly, it disables
     479                // otherwise-identical calls, like this example based on auto-newline in the I/O lib:
     480                //
     481                //   forall(otype OS) {
     482                //     void ?|?(OS&, int);  // with newline
     483                //     OS&  ?|?(OS&, int);  // no newline, always chosen due to more specialization
     484                //   }
     485
     486                // mark type variable and specialization cost of forall clause
     487                convCost.incVar( function->forall.size() );
     488                for ( TypeDecl* td : function->forall ) {
     489                        convCost.decSpec( td->assertions.size() );
    452490                }
    453491
     
    462500                                needAssertions[ *assert ].isUsed = true;
    463501                        }
    464 ///     needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() );
    465                 }
    466         }
    467 
    468         static const int recursionLimit = /*10*/ 4;  ///< Limit to depth of recursion satisfaction
    469 
    470         void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) {
    471                 for ( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i ) {
    472                         if ( i->second.isUsed ) {
    473                                 indexer.addId( i->first );
    474                         }
    475                 }
    476         }
    477 
    478         template< typename ForwardIterator, typename OutputIterator >
    479         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 ) {
    480                 if ( begin == end ) {
    481                         if ( newNeed.empty() ) {
    482                                 PRINT(
    483                                         std::cerr << "all assertions satisfied, output alternative: ";
    484                                         newAlt.print( std::cerr );
    485                                         std::cerr << std::endl;
    486                                 );
    487                                 *out++ = newAlt;
    488                                 return;
    489                         } else if ( level >= recursionLimit ) {
    490                                 SemanticError( newAlt.expr->location, "Too many recursive assertions" );
    491                         } else {
    492                                 AssertionSet newerNeed;
    493                                 PRINT(
    494                                         std::cerr << "recursing with new set:" << std::endl;
    495                                         printAssertionSet( newNeed, std::cerr, 8 );
    496                                 )
    497                                 inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out );
    498                                 return;
    499                         }
    500                 }
    501 
    502                 ForwardIterator cur = begin++;
    503                 if ( ! cur->second.isUsed ) {
    504                         inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out );
    505                         return; // xxx - should this continue? previously this wasn't here, and it looks like it should be
    506                 }
    507                 DeclarationWithType *curDecl = cur->first;
    508 
    509                 PRINT(
    510                         std::cerr << "inferRecursive: assertion is ";
    511                         curDecl->print( std::cerr );
    512                         std::cerr << std::endl;
    513                 )
    514                 std::list< SymTab::Indexer::IdData > candidates;
    515                 decls.lookupId( curDecl->get_name(), candidates );
    516 ///   if ( candidates.empty() ) { std::cerr << "no candidates!" << std::endl; }
    517                 for ( const auto & data : candidates ) {
    518                         DeclarationWithType * candidate = data.id;
    519                         PRINT(
    520                                 std::cerr << "inferRecursive: candidate is ";
    521                                 candidate->print( std::cerr );
    522                                 std::cerr << std::endl;
    523                         )
    524 
    525                         AssertionSet newHave, newerNeed( newNeed );
    526                         TypeEnvironment newEnv( newAlt.env );
    527                         OpenVarSet newOpenVars( openVars );
    528                         Type *adjType = candidate->get_type()->clone();
    529                         adjustExprType( adjType, newEnv, indexer );
    530                         renameTyVars( adjType );
    531                         PRINT(
    532                                 std::cerr << "unifying ";
    533                                 curDecl->get_type()->print( std::cerr );
    534                                 std::cerr << " with ";
    535                                 adjType->print( std::cerr );
    536                                 std::cerr << std::endl;
    537                         )
    538                         if ( unify( curDecl->get_type(), adjType, newEnv, newerNeed, newHave, newOpenVars, indexer ) ) {
    539                                 PRINT(
    540                                         std::cerr << "success!" << std::endl;
    541                                 )
    542                                 SymTab::Indexer newDecls( decls );
    543                                 addToIndexer( newHave, newDecls );
    544                                 Alternative newerAlt( newAlt );
    545                                 newerAlt.env = newEnv;
    546                                 assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
    547 
    548                                 // everything with an empty idChain was pulled in by the current assertion.
    549                                 // add current assertion's idChain + current assertion's ID so that the correct inferParameters can be found.
    550                                 for ( auto & a : newerNeed ) {
    551                                         if ( a.second.idChain.empty() ) {
    552                                                 a.second.idChain = cur->second.idChain;
    553                                                 a.second.idChain.push_back( curDecl->get_uniqueId() );
    554                                         }
    555                                 }
    556 
    557                                 Expression *varExpr = data.combine( newerAlt.cvtCost );
    558                                 delete varExpr->get_result();
    559                                 varExpr->set_result( adjType->clone() );
    560                                 PRINT(
    561                                         std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " ";
    562                                         curDecl->print( std::cerr );
    563                                         std::cerr << " with declaration " << candidate->get_uniqueId() << " ";
    564                                         candidate->print( std::cerr );
    565                                         std::cerr << std::endl;
    566                                 )
    567                                 // 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).
    568                                 InferredParams * inferParameters = &newerAlt.expr->get_inferParams();
    569                                 for ( UniqueId id : cur->second.idChain ) {
    570                                         inferParameters = (*inferParameters)[ id ].inferParams.get();
    571                                 }
    572                                 // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions
    573                                 (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );
    574                                 inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out );
    575                         } else {
    576                                 delete adjType;
    577                         }
    578                 }
    579         }
     502                }
     503        }
     504
     505        /// Unique identifier for matching expression resolutions to their requesting expression (located in CandidateFinder.cpp)
     506        extern UniqueId globalResnSlot;
    580507
    581508        template< typename OutputIterator >
    582         void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {
    583 //      PRINT(
    584 //          std::cerr << "inferParameters: assertions needed are" << std::endl;
    585 //          printAll( need, std::cerr, 8 );
    586 //          )
    587                 SymTab::Indexer decls( indexer );
    588                 // PRINT(
    589                 //      std::cerr << "============= original indexer" << std::endl;
    590                 //      indexer.print( std::cerr );
    591                 //      std::cerr << "============= new indexer" << std::endl;
    592                 //      decls.print( std::cerr );
    593                 // )
    594                 addToIndexer( have, decls );
    595                 AssertionSet newNeed;
    596                 PRINT(
    597                         std::cerr << "env is: " << std::endl;
    598                         newAlt.env.print( std::cerr, 0 );
    599                         std::cerr << std::endl;
    600                 )
    601 
    602                 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out );
    603 //      PRINT(
    604 //          std::cerr << "declaration 14 is ";
    605 //          Declaration::declFromId
    606 //          *out++ = newAlt;
    607 //          )
     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;
    608525        }
    609526
     
    611528        ConstantExpr* getDefaultValue( Initializer* init ) {
    612529                if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) {
    613                         if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) {
    614                                 return dynamic_cast<ConstantExpr*>( ce->get_arg() );
     530                        if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->value ) ) {
     531                                return dynamic_cast<ConstantExpr*>( ce->arg );
     532                        } else {
     533                                return dynamic_cast<ConstantExpr*>( si->value );
    615534                        }
    616535                }
     
    659578
    660579                /// Gets the list of exploded alternatives for this pack
    661                 const ExplodedActual& getExpl( const ExplodedArgs& args ) const {
     580                const ExplodedActual& getExpl( const ExplodedArgs_old& args ) const {
    662581                        return args[nextArg-1][explAlt];
    663582                }
     
    683602        /// Instantiates an argument to match a formal, returns false if no results left
    684603        bool instantiateArgument( Type* formalType, Initializer* initializer,
    685                         const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart,
     604                        const ExplodedArgs_old& args, std::vector<ArgPack>& results, std::size_t& genStart,
    686605                        const SymTab::Indexer& indexer, unsigned nTuples = 0 ) {
    687606                if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) {
     
    873792                                                                indexer ) ) {
    874793                                                        results.emplace_back(
    875                                                                 i, cnstExpr, move(env), move(need), move(have),
     794                                                                i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have),
    876795                                                                move(openVars), nextArg, nTuples );
    877796                                                }
     
    944863                }
    945864                // build and validate new alternative
    946                 Alternative newAlt( appExpr, result.env, cost );
     865                Alternative newAlt{ appExpr, result.env, result.openVars, result.need, cost };
    947866                PRINT(
    948867                        std::cerr << "instantiate function success: " << appExpr << std::endl;
     
    950869                        printAssertionSet( result.need, std::cerr, 8 );
    951870                )
    952                 inferParameters( result.need, result.have, newAlt, result.openVars, out );
     871                inferParameters( newAlt, out );
    953872        }
    954873
    955874        template<typename OutputIterator>
    956875        void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func,
    957                         FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) {
     876                        FunctionType *funcType, const ExplodedArgs_old &args, OutputIterator out ) {
    958877                OpenVarSet funcOpenVars;
    959878                AssertionSet funcNeed, funcHave;
     
    1065984                funcFinder.findWithAdjustment( untypedExpr->function );
    1066985                // if there are no function alternatives, then proceeding is a waste of time.
     986                // xxx - findWithAdjustment throws, so this check and others like it shouldn't be necessary.
    1067987                if ( funcFinder.alternatives.empty() ) return;
    1068988
     
    10861006
    10871007                // pre-explode arguments
    1088                 ExplodedArgs argExpansions;
     1008                ExplodedArgs_old argExpansions;
    10891009                argExpansions.reserve( argAlternatives.size() );
    10901010
     
    10921012                        argExpansions.emplace_back();
    10931013                        auto& argE = argExpansions.back();
    1094                         argE.reserve( arg.alternatives.size() );
     1014                        // argE.reserve( arg.alternatives.size() );
    10951015
    10961016                        for ( const Alternative& actual : arg ) {
     
    11781098                                std::cerr << "bindings are:" << std::endl;
    11791099                                withFunc.env.print( std::cerr, 8 );
     1100                                std::cerr << "cost is: " << withFunc.cost << std::endl;
    11801101                                std::cerr << "cost of conversion is:" << cvtCost << std::endl;
    11811102                        )
     
    11931114
    11941115                // function may return struct or union value, in which case we need to add alternatives
    1195                 // 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
    11961117                // since anon conversions are never the cheapest expression
    11971118                for ( const Alternative & alt : winners ) {
     
    12161137        bool isLvalue( Expression *expr ) {
    12171138                // xxx - recurse into tuples?
    1218                 return expr->result && ( expr->result->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) );
     1139                return expr->result && ( expr->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) );
    12191140        }
    12201141
     
    12251146                        if ( isLvalue( alt.expr ) ) {
    12261147                                alternatives.push_back(
    1227                                         Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } );
     1148                                        Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } );
    12281149                        } // if
    12291150                } // for
     
    12311152
    12321153        void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) {
    1233                 alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } );
     1154                alternatives.push_back( Alternative{ expr->clone(), env } );
    12341155        }
    12351156
     
    12671188                assert( toType );
    12681189                toType = resolveTypeof( toType, indexer );
     1190                assert(!dynamic_cast<TypeofType *>(toType));
    12691191                SymTab::validateType( toType, &indexer );
    12701192                adjustExprType( toType, env, indexer );
     
    12761198                AltList candidates;
    12771199                for ( Alternative & alt : finder.alternatives ) {
    1278                         AssertionSet needAssertions, haveAssertions;
    1279                         OpenVarSet openVars;
     1200                        AssertionSet needAssertions( alt.need.begin(), alt.need.end() );
     1201                        AssertionSet haveAssertions;
     1202                        OpenVarSet openVars{ alt.openVars };
    12801203
    12811204                        alt.env.extractOpenVars( openVars );
     
    12921215                        unify( castExpr->result, alt.expr->result, alt.env, needAssertions,
    12931216                                haveAssertions, openVars, indexer );
    1294                         Cost thisCost = castCost( alt.expr->result, castExpr->result, indexer,
    1295                                 alt.env );
     1217                        Cost thisCost = castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(),
     1218                                indexer, alt.env );
    12961219                        PRINT(
    12971220                                std::cerr << "working on cast with result: " << castExpr->result << std::endl;
     
    13051228                                // count one safe conversion for each value that is thrown away
    13061229                                thisCost.incSafe( discardedValues );
    1307                                 Alternative newAlt( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env,
    1308                                         alt.cost, thisCost );
    1309                                 inferParameters( needAssertions, haveAssertions, newAlt, openVars,
    1310                                         back_inserter( candidates ) );
     1230                                Alternative newAlt{
     1231                                        restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ),
     1232                                        alt.env, openVars, needAssertions, alt.cost, alt.cost + thisCost };
     1233                                inferParameters( newAlt, back_inserter( candidates ) );
    13111234                        } // if
    13121235                } // for
     
    13211244
    13221245        void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) {
    1323                 assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." );
     1246                assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." );
    13241247                AlternativeFinder finder( indexer, env );
    13251248                // don't prune here, since it's guaranteed all alternatives will have the same type
    13261249                finder.findWithoutPrune( castExpr->get_arg() );
    13271250                for ( Alternative & alt : finder.alternatives ) {
    1328                         alternatives.push_back( Alternative(
    1329                                 new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ),
    1330                                 alt.env, alt.cost ) );
     1251                        alternatives.push_back( Alternative{
     1252                                alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() },
     1253                                alt.cost } );
    13311254                }
    13321255        }
     
    13351258                /// Gets name from untyped member expression (member must be NameExpr)
    13361259                const std::string& get_member_name( UntypedMemberExpr *memberExpr ) {
     1260                        if ( dynamic_cast< ConstantExpr * >( memberExpr->get_member() ) ) {
     1261                                SemanticError( memberExpr, "Indexed access to struct fields unsupported: " );
     1262                        } // if
    13371263                        NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() );
    13381264                        assert( nameExpr );
     
    13531279                        // find member of the given type
    13541280                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    1355                                 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
     1281                                addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
    13561282                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    1357                                 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
     1283                                addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
    13581284                        } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
    1359                                 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );
     1285                                addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() );
    13601286                        } // if
    13611287                } // for
     
    13631289
    13641290        void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) {
    1365                 alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) );
     1291                alternatives.push_back( Alternative{ memberExpr->clone(), env } );
    13661292        }
    13671293
     
    13761302                        // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    13771303                        // can't construct in place and use vector::back
    1378                         Alternative newAlt( newExpr, env, Cost::zero, cost );
     1304                        Alternative newAlt{ newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost };
    13791305                        PRINT(
    13801306                                std::cerr << "decl is ";
     
    13941320                // not sufficient to clone here, because variable's type may have changed
    13951321                // since the VariableExpr was originally created.
    1396                 alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) );
     1322                alternatives.push_back( Alternative{ new VariableExpr{ variableExpr->var }, env } );
    13971323        }
    13981324
    13991325        void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) {
    1400                 alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) );
     1326                alternatives.push_back( Alternative{ constantExpr->clone(), env } );
    14011327        }
    14021328
     
    14041330                if ( sizeofExpr->get_isType() ) {
    14051331                        Type * newType = sizeofExpr->get_type()->clone();
    1406                         alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
     1332                        alternatives.push_back( Alternative{
     1333                                new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } );
    14071334                } else {
    14081335                        // find all alternatives for the argument to sizeof
     
    14181345                        Alternative &choice = winners.front();
    14191346                        referenceToRvalueConversion( choice.expr, choice.cost );
    1420                         alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
     1347                        alternatives.push_back( Alternative{
     1348                                choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } );
    14211349                } // if
    14221350        }
     
    14251353                if ( alignofExpr->get_isType() ) {
    14261354                        Type * newType = alignofExpr->get_type()->clone();
    1427                         alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
     1355                        alternatives.push_back( Alternative{
     1356                                new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } );
    14281357                } else {
    14291358                        // find all alternatives for the argument to sizeof
     
    14391368                        Alternative &choice = winners.front();
    14401369                        referenceToRvalueConversion( choice.expr, choice.cost );
    1441                         alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
     1370                        alternatives.push_back( Alternative{
     1371                                choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } );
    14421372                } // if
    14431373        }
     
    14491379                for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    14501380                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
    1451                                 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) );
     1381                                alternatives.push_back( Alternative{
     1382                                        new OffsetofExpr{ aggInst->clone(), dwt }, env } );
    14521383                                renameTypes( alternatives.back().expr );
    14531384                        } else {
     
    14681399
    14691400        void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) {
    1470                 alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) );
     1401                alternatives.push_back( Alternative{ offsetofExpr->clone(), env } );
    14711402        }
    14721403
    14731404        void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) {
    1474                 alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) );
    1475         }
    1476 
    1477         namespace {
    1478                 void resolveAttr( SymTab::Indexer::IdData data, FunctionType *function, Type *argType, const TypeEnvironment &env, AlternativeFinder & finder ) {
    1479                         // assume no polymorphism
    1480                         // assume no implicit conversions
    1481                         assert( function->get_parameters().size() == 1 );
    1482                         PRINT(
    1483                                 std::cerr << "resolvAttr: funcDecl is ";
    1484                                 data.id->print( std::cerr );
    1485                                 std::cerr << " argType is ";
    1486                                 argType->print( std::cerr );
    1487                                 std::cerr << std::endl;
    1488                         )
    1489                         const SymTab::Indexer & indexer = finder.get_indexer();
    1490                         AltList & alternatives = finder.get_alternatives();
    1491                         if ( typesCompatibleIgnoreQualifiers( argType, function->get_parameters().front()->get_type(), indexer, env ) ) {
    1492                                 Cost cost = Cost::zero;
    1493                                 Expression * newExpr = data.combine( cost );
    1494                                 alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) );
    1495                                 for ( DeclarationWithType * retVal : function->returnVals ) {
    1496                                         alternatives.back().expr->result = retVal->get_type()->clone();
    1497                                 } // for
    1498                         } // if
    1499                 }
    1500         }
    1501 
    1502         void AlternativeFinder::Finder::postvisit( AttrExpr *attrExpr ) {
    1503                 // assume no 'pointer-to-attribute'
    1504                 NameExpr *nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() );
    1505                 assert( nameExpr );
    1506                 std::list< SymTab::Indexer::IdData > attrList;
    1507                 indexer.lookupId( nameExpr->get_name(), attrList );
    1508                 if ( attrExpr->get_isType() || attrExpr->get_expr() ) {
    1509                         for ( auto & data : attrList ) {
    1510                                 DeclarationWithType * id = data.id;
    1511                                 // check if the type is function
    1512                                 if ( FunctionType *function = dynamic_cast< FunctionType* >( id->get_type() ) ) {
    1513                                         // assume exactly one parameter
    1514                                         if ( function->get_parameters().size() == 1 ) {
    1515                                                 if ( attrExpr->get_isType() ) {
    1516                                                         resolveAttr( data, function, attrExpr->get_type(), env, altFinder);
    1517                                                 } else {
    1518                                                         AlternativeFinder finder( indexer, env );
    1519                                                         finder.find( attrExpr->get_expr() );
    1520                                                         for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) {
    1521                                                                 if ( choice->expr->get_result()->size() == 1 ) {
    1522                                                                         resolveAttr(data, function, choice->expr->get_result(), choice->env, altFinder );
    1523                                                                 } // fi
    1524                                                         } // for
    1525                                                 } // if
    1526                                         } // if
    1527                                 } // if
    1528                         } // for
    1529                 } else {
    1530                         for ( auto & data : attrList ) {
    1531                                 Cost cost = Cost::zero;
    1532                                 Expression * newExpr = data.combine( cost );
    1533                                 alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) );
    1534                                 renameTypes( alternatives.back().expr );
    1535                         } // for
    1536                 } // if
    1537         }
    1538 
    1539         void AlternativeFinder::Finder::postvisit( LogicalExpr *logicalExpr ) {
     1405                alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } );
     1406        }
     1407
     1408        void AlternativeFinder::Finder::postvisit( LogicalExpr * logicalExpr ) {
    15401409                AlternativeFinder firstFinder( indexer, env );
    15411410                firstFinder.findWithAdjustment( logicalExpr->get_arg1() );
     
    15461415                for ( const Alternative & first : firstFinder.alternatives ) {
    15471416                        for ( const Alternative & second : secondFinder.alternatives ) {
    1548                                 TypeEnvironment compositeEnv;
    1549                                 compositeEnv.simpleCombine( first.env );
     1417                                TypeEnvironment compositeEnv{ first.env };
    15501418                                compositeEnv.simpleCombine( second.env );
    1551 
    1552                                 LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() );
    1553                                 alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) );
     1419                                OpenVarSet openVars{ first.openVars };
     1420                                mergeOpenVars( openVars, second.openVars );
     1421                                AssertionSet need;
     1422                                cloneAll( first.need, need );
     1423                                cloneAll( second.need, need );
     1424
     1425                                LogicalExpr *newExpr = new LogicalExpr{
     1426                                        first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() };
     1427                                alternatives.push_back( Alternative{
     1428                                        newExpr, std::move(compositeEnv), std::move(openVars),
     1429                                        AssertionList( need.begin(), need.end() ), first.cost + second.cost } );
    15541430                        }
    15551431                }
     
    15721448                        for ( const Alternative & second : secondFinder.alternatives ) {
    15731449                                for ( const Alternative & third : thirdFinder.alternatives ) {
    1574                                         TypeEnvironment compositeEnv;
    1575                                         compositeEnv.simpleCombine( first.env );
     1450                                        TypeEnvironment compositeEnv{ first.env };
    15761451                                        compositeEnv.simpleCombine( second.env );
    15771452                                        compositeEnv.simpleCombine( third.env );
     1453                                        OpenVarSet openVars{ first.openVars };
     1454                                        mergeOpenVars( openVars, second.openVars );
     1455                                        mergeOpenVars( openVars, third.openVars );
     1456                                        AssertionSet need;
     1457                                        cloneAll( first.need, need );
     1458                                        cloneAll( second.need, need );
     1459                                        cloneAll( third.need, need );
     1460                                        AssertionSet have;
    15781461
    15791462                                        // unify true and false types, then infer parameters to produce new alternatives
    1580                                         OpenVarSet openVars;
    1581                                         AssertionSet needAssertions, haveAssertions;
    1582                                         Alternative newAlt( 0, compositeEnv, first.cost + second.cost + third.cost );
    15831463                                        Type* commonType = nullptr;
    1584                                         if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    1585                                                 ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() );
     1464                                        if ( unify( second.expr->result, third.expr->result, compositeEnv,
     1465                                                        need, have, openVars, indexer, commonType ) ) {
     1466                                                ConditionalExpr *newExpr = new ConditionalExpr{
     1467                                                        first.expr->clone(), second.expr->clone(), third.expr->clone() };
    15861468                                                newExpr->result = commonType ? commonType : second.expr->result->clone();
    15871469                                                // convert both options to the conditional result type
    1588                                                 newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env );
    1589                                                 newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env );
    1590                                                 newAlt.expr = newExpr;
    1591                                                 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
     1470                                                Cost cost = first.cost + second.cost + third.cost;
     1471                                                cost += computeExpressionConversionCost(
     1472                                                        newExpr->arg2, newExpr->result, indexer, compositeEnv );
     1473                                                cost += computeExpressionConversionCost(
     1474                                                        newExpr->arg3, newExpr->result, indexer, compositeEnv );
     1475                                                // output alternative
     1476                                                Alternative newAlt{
     1477                                                        newExpr, std::move(compositeEnv), std::move(openVars),
     1478                                                        AssertionList( need.begin(), need.end() ), cost };
     1479                                                inferParameters( newAlt, back_inserter( alternatives ) );
    15921480                                        } // if
    15931481                                } // for
     
    16021490                secondFinder.findWithAdjustment( commaExpr->get_arg2() );
    16031491                for ( const Alternative & alt : secondFinder.alternatives ) {
    1604                         alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) );
     1492                        alternatives.push_back( Alternative{
     1493                                alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } );
    16051494                } // for
    16061495                delete newFirstArg;
     
    16171506                for ( const Alternative & first : firstFinder.alternatives ) {
    16181507                        for ( const Alternative & second : secondFinder.alternatives ) {
    1619                                 TypeEnvironment compositeEnv;
    1620                                 compositeEnv.simpleCombine( first.env );
     1508                                TypeEnvironment compositeEnv{ first.env };
    16211509                                compositeEnv.simpleCombine( second.env );
    1622                                 OpenVarSet openVars;
    1623                                 AssertionSet needAssertions, haveAssertions;
    1624                                 Alternative newAlt( 0, compositeEnv, first.cost + second.cost );
     1510                                OpenVarSet openVars{ first.openVars };
     1511                                mergeOpenVars( openVars, second.openVars );
     1512                                AssertionSet need;
     1513                                cloneAll( first.need, need );
     1514                                cloneAll( second.need, need );
     1515                                AssertionSet have;
     1516
    16251517                                Type* commonType = nullptr;
    1626                                 if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    1627                                         RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() );
     1518                                if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have,
     1519                                                openVars, indexer, commonType ) ) {
     1520                                        RangeExpr * newExpr =
     1521                                                new RangeExpr{ first.expr->clone(), second.expr->clone() };
    16281522                                        newExpr->result = commonType ? commonType : first.expr->result->clone();
    1629                                         newAlt.expr = newExpr;
    1630                                         inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
     1523                                        Alternative newAlt{
     1524                                                newExpr, std::move(compositeEnv), std::move(openVars),
     1525                                                AssertionList( need.begin(), need.end() ), first.cost + second.cost };
     1526                                        inferParameters( newAlt, back_inserter( alternatives ) );
    16311527                                } // if
    16321528                        } // for
     
    16461542
    16471543                        TypeEnvironment compositeEnv;
    1648                         simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv );
    1649                         alternatives.push_back(
    1650                                 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } );
     1544                        OpenVarSet openVars;
     1545                        AssertionSet need;
     1546                        for ( const Alternative& alt : alts ) {
     1547                                compositeEnv.simpleCombine( alt.env );
     1548                                mergeOpenVars( openVars, alt.openVars );
     1549                                cloneAll( alt.need, need );
     1550                        }
     1551
     1552                        alternatives.push_back( Alternative{
     1553                                new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars),
     1554                                AssertionList( need.begin(), need.end() ), sumCost( alts ) } );
    16511555                } // for
    16521556        }
    16531557
    16541558        void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) {
    1655                 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
     1559                alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
    16561560        }
    16571561
    16581562        void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    1659                 alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );
     1563                alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } );
    16601564        }
    16611565
     
    16661570                finder.findWithoutPrune( ctorExpr->get_callExpr() );
    16671571                for ( Alternative & alt : finder.alternatives ) {
    1668                         alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) );
     1572                        alternatives.push_back( Alternative{
     1573                                alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } );
    16691574                }
    16701575        }
    16711576
    16721577        void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) {
    1673                 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
     1578                alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
    16741579        }
    16751580
    16761581        void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) {
    1677                 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) );
     1582                alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } );
    16781583        }
    16791584
     
    16841589                        // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked"
    16851590                        UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() );
    1686                         alternatives.push_back( Alternative( newUnqExpr, alt.env, alt.cost ) );
     1591                        alternatives.push_back( Alternative{ alt, newUnqExpr, alt.cost } );
    16871592                }
    16881593        }
     
    16921597                ResolvExpr::resolveStmtExpr( newStmtExpr, indexer );
    16931598                // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr...
    1694                 alternatives.push_back( Alternative( newStmtExpr, env, Cost::zero ) );
     1599                alternatives.push_back( Alternative{ newStmtExpr, env } );
    16951600        }
    16961601
     
    17141619                        for ( Alternative & alt : finder.get_alternatives() ) {
    17151620                                TypeEnvironment newEnv( alt.env );
    1716                                 AssertionSet needAssertions, haveAssertions;
    1717                                 OpenVarSet openVars;  // find things in env that don't have a "representative type" and claim those are open vars?
     1621                                AssertionSet need;
     1622                                cloneAll( alt.need, need );
     1623                                AssertionSet have;
     1624                                OpenVarSet openVars( alt.openVars );
     1625                                // xxx - find things in env that don't have a "representative type" and claim
     1626                                // those are open vars?
    17181627                                PRINT(
    17191628                                        std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
    17201629                                )
    1721                                 // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
    1722                                 // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
    1723                                 // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    1724                                 // to.
     1630                                // It's possible that a cast can throw away some values in a multiply-valued
     1631                                // expression. (An example is a cast-to-void, which casts from one value to
     1632                                // zero.)  Figure out the prefix of the subexpression results that are cast
     1633                                // directly.  The candidate is invalid if it has fewer results than there are
     1634                                // types to cast to.
    17251635                                int discardedValues = alt.expr->result->size() - toType->size();
    17261636                                if ( discardedValues < 0 ) continue;
    1727                                 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    1728                                 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
     1637                                // xxx - may need to go into tuple types and extract relevant types and use
     1638                                // unifyList. Note that currently, this does not allow casting a tuple to an
     1639                                // atomic type (e.g. (int)([1, 2, 3]))
     1640
    17291641                                // unification run for side-effects
    1730                                 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??
    1731 
    1732                                 Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv );
     1642                                unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer );
     1643                                // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?
     1644
     1645                                Cost thisCost = castCost( alt.expr->result, toType, alt.expr->get_lvalue(),
     1646                                        indexer, newEnv );
    17331647                                if ( thisCost != Cost::infinity ) {
    17341648                                        // count one safe conversion for each value that is thrown away
    17351649                                        thisCost.incSafe( discardedValues );
    1736                                         Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost );
    1737                                         inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
     1650                                        Alternative newAlt{
     1651                                                new InitExpr{
     1652                                                        restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() },
     1653                                                std::move(newEnv), std::move(openVars),
     1654                                                AssertionList( need.begin(), need.end() ), alt.cost, thisCost };
     1655                                        inferParameters( newAlt, back_inserter( candidates ) );
    17381656                                }
    17391657                        }
Note: See TracChangeset for help on using the changeset viewer.