Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    rda6032af rd1e0979  
    1010// Created On       : Sat May 16 23:52:08 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Nov  1 21:00:56 2018
    13 // Update Count     : 35
     12// Last Modified On : Sat Feb 17 11:19:39 2018
     13// Update Count     : 33
    1414//
    1515
     
    2525#include <vector>                  // for vector
    2626
    27 #include "CompilationState.h"      // for resolvep
    2827#include "Alternative.h"           // for AltList, Alternative
    2928#include "AlternativeFinder.h"
     
    3433#include "InitTweak/InitTweak.h"   // for getFunctionName
    3534#include "RenameVars.h"            // for RenameVars, global_renamer
    36 #include "ResolveAssertions.h"     // for resolveAssertions
    3735#include "ResolveTypeof.h"         // for resolveTypeof
    3836#include "Resolver.h"              // for resolveStmtExpr
     
    5149#include "typeops.h"               // for adjustExprType, polyCost, castCost
    5250
     51bool resolvep;
    5352#define PRINT( text ) if ( resolvep ) { text }
    5453//#define DEBUG_COST
     
    103102                void addAnonConversions( const Alternative & alt );
    104103                /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
    105                 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative &alt, const Cost &newCost, const std::string & name );
     104                template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name );
    106105                /// Adds alternatives for member expressions where the left side has tuple type
    107                 void addTupleMembers( TupleType *tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member );
     106                void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
    108107                /// Adds alternatives for offsetof expressions, given the base type and name of the member
    109108                template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
     
    114113                template<typename OutputIterator>
    115114                void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out );
    116                 /// Sets up parameter inference for an output alternative
     115                /// Checks if assertion parameters match for a new alternative
    117116                template< typename OutputIterator >
    118                 void inferParameters( Alternative &newAlt, OutputIterator out );
     117                void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
    119118        private:
    120119                AlternativeFinder & altFinder;
     
    245244        }
    246245
    247         void AlternativeFinder::find( Expression *expr, ResolvMode mode ) {
     246        void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) {
    248247                PassVisitor<Finder> finder( *this );
    249248                expr->accept( finder );
    250                 if ( mode.failFast && alternatives.empty() ) {
     249                if ( failFast && alternatives.empty() ) {
    251250                        PRINT(
    252251                                std::cerr << "No reasonable alternatives for expression " << expr << std::endl;
     
    254253                        SemanticError( expr, "No reasonable alternatives for expression " );
    255254                }
    256                 if ( mode.resolveAssns || mode.prune ) {
    257                         // trim candidates just to those where the assertions resolve
    258                         // - necessary pre-requisite to pruning
    259                         AltList candidates;
    260                         for ( unsigned i = 0; i < alternatives.size(); ++i ) {
    261                                 resolveAssertions( alternatives[i], indexer, candidates );
    262                         }
    263                         // fail early if none such
    264                         if ( mode.failFast && candidates.empty() ) {
    265                                 std::ostringstream stream;
    266                                 stream << "No resolvable alternatives for expression " << expr << "\n"
    267                                        << "Alternatives with failing assertions are:\n";
    268                                 printAlts( alternatives, stream, 1 );
    269                                 SemanticError( expr->location, stream.str() );
    270                         }
    271                         // reset alternatives
    272                         alternatives = std::move( candidates );
    273                 }
    274                 if ( mode.prune ) {
     255                if ( prune ) {
    275256                        auto oldsize = alternatives.size();
    276257                        PRINT(
     
    280261                        AltList pruned;
    281262                        pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) );
    282                         if ( mode.failFast && pruned.empty() ) {
     263                        if ( failFast && pruned.empty() ) {
    283264                                std::ostringstream stream;
    284265                                AltList winners;
     
    299280                }
    300281                // adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted
    301                 if ( mode.adjust ) {
    302                         for ( Alternative& i : alternatives ) {
    303                                 adjustExprType( i.expr->get_result(), i.env, indexer );
     282                for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
     283                        if ( adjust ) {
     284                                adjustExprType( i->expr->get_result(), i->env, indexer );
    304285                        }
    305286                }
     
    313294
    314295        void AlternativeFinder::findWithAdjustment( Expression *expr ) {
    315                 find( expr, ResolvMode::withAdjustment() );
     296                find( expr, true );
    316297        }
    317298
    318299        void AlternativeFinder::findWithoutPrune( Expression * expr ) {
    319                 find( expr, ResolvMode::withoutPrune() );
     300                find( expr, true, false );
    320301        }
    321302
    322303        void AlternativeFinder::maybeFind( Expression * expr ) {
    323                 find( expr, ResolvMode::withoutFailFast() );
     304                find( expr, true, true, false );
    324305        }
    325306
     
    336317
    337318                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
    338                         addAggMembers( structInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
     319                        addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
    339320                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
    340                         addAggMembers( unionInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
     321                        addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
    341322                } // if
    342323        }
    343324
    344325        template< typename StructOrUnionType >
    345         void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative& alt, const Cost &newCost, const std::string & name ) {
     326        void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) {
    346327                std::list< Declaration* > members;
    347328                aggInst->lookup( name, members );
     
    351332                                // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    352333                                // can't construct in place and use vector::back
    353                                 Alternative newAlt{ alt, new MemberExpr{ dwt, expr->clone() }, newCost };
     334                                Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost );
    354335                                renameTypes( newAlt.expr );
    355336                                addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
     
    361342        }
    362343
    363         void AlternativeFinder::Finder::addTupleMembers( TupleType *tupleType, Expression *expr,                        const Alternative &alt, const Cost &newCost, Expression *member ) {
     344        void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    364345                if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
    365346                        // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
     
    367348                        std::string tmp;
    368349                        if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    369                                 alternatives.push_back( Alternative{
    370                                         alt, new TupleIndexExpr( expr->clone(), val ), newCost } );
     350                                alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
    371351                        } // if
    372352                } // if
     
    374354
    375355        void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) {
    376                 alternatives.push_back( Alternative{ applicationExpr->clone(), env } );
     356                alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) );
    377357        }
    378358
     
    430410        Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
    431411                ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( alt.expr );
    432                 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result );
    433                 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base );
     412                PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
     413                FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() );
    434414
    435415                Cost convCost = Cost::zero;
    436                 std::list< DeclarationWithType* >& formals = function->parameters;
     416                std::list< DeclarationWithType* >& formals = function->get_parameters();
    437417                std::list< DeclarationWithType* >::iterator formal = formals.begin();
    438                 std::list< Expression* >& actuals = appExpr->args;
    439 
    440                 for ( Expression*& actualExpr : actuals ) {
    441                         Type * actualType = actualExpr->result;
     418                std::list< Expression* >& actuals = appExpr->get_args();
     419
     420                for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
     421                        Type * actualType = (*actualExpr)->get_result();
    442422                        PRINT(
    443423                                std::cerr << "actual expression:" << std::endl;
    444                                 actualExpr->print( std::cerr, 8 );
     424                                (*actualExpr)->print( std::cerr, 8 );
    445425                                std::cerr << "--- results are" << std::endl;
    446426                                actualType->print( std::cerr, 8 );
    447427                        )
    448428                        if ( formal == formals.end() ) {
    449                                 if ( function->isVarArgs ) {
     429                                if ( function->get_isVarArgs() ) {
    450430                                        convCost.incUnsafe();
    451431                                        PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; )
    452432                                        // convert reference-typed expressions to value-typed expressions
    453                                         referenceToRvalueConversion( actualExpr, convCost );
     433                                        referenceToRvalueConversion( *actualExpr, convCost );
    454434                                        continue;
    455435                                } else {
     
    457437                                }
    458438                        }
    459                         if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( actualExpr ) ) {
     439                        if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) {
    460440                                // default arguments should be free - don't include conversion cost.
    461441                                // Unwrap them here because they are not relevant to the rest of the system.
    462                                 actualExpr = def->expr;
     442                                *actualExpr = def->expr;
    463443                                ++formal;
    464444                                continue;
    465445                        }
    466                         // mark conversion cost to formal and also specialization cost of formal type
    467446                        Type * formalType = (*formal)->get_type();
    468                         convCost += computeExpressionConversionCost( actualExpr, formalType, indexer, alt.env );
    469                         convCost.decSpec( specCost( formalType ) );
     447                        convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env );
    470448                        ++formal; // can't be in for-loop update because of the continue
    471449                }
     
    474452                }
    475453
    476                 // specialization cost of return types can't be accounted for directly, it disables
    477                 // otherwise-identical calls, like this example based on auto-newline in the I/O lib:
    478                 //
    479                 //   forall(otype OS) {
    480                 //     void ?|?(OS&, int);  // with newline
    481                 //     OS&  ?|?(OS&, int);  // no newline, always chosen due to more specialization
    482                 //   }
    483 
    484                 // mark type variable and specialization cost of forall clause
    485                 convCost.incVar( function->forall.size() );
    486                 for ( TypeDecl* td : function->forall ) {
    487                         convCost.decSpec( td->assertions.size() );
     454                for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) {
     455                        convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env );
    488456                }
    489457
     
    498466                                needAssertions[ *assert ].isUsed = true;
    499467                        }
    500                 }
    501         }
    502 
    503         /// Unique identifier for matching expression resolutions to their requesting expression
    504         UniqueId globalResnSlot = 0;
     468///     needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() );
     469                }
     470        }
     471
     472        static const int recursionLimit = /*10*/ 4;  ///< Limit to depth of recursion satisfaction
     473
     474        void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) {
     475                for ( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i ) {
     476                        if ( i->second.isUsed ) {
     477                                indexer.addId( i->first );
     478                        }
     479                }
     480        }
     481
     482        template< typename ForwardIterator, typename OutputIterator >
     483        void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, int level, const SymTab::Indexer &indexer, OutputIterator out ) {
     484                if ( newAlt.cost == Cost::infinity ) return; // don't proceed down this dead end
     485                if ( begin == end ) {
     486                        if ( newNeed.empty() ) {
     487                                PRINT(
     488                                        std::cerr << "all assertions satisfied, output alternative: ";
     489                                        newAlt.print( std::cerr );
     490                                        std::cerr << std::endl;
     491                                );
     492                                *out++ = newAlt;
     493                                return;
     494                        } else if ( level >= recursionLimit ) {
     495                                SemanticError( newAlt.expr->location, "Too many recursive assertions" );
     496                        } else {
     497                                AssertionSet newerNeed;
     498                                PRINT(
     499                                        std::cerr << "recursing with new set:" << std::endl;
     500                                        printAssertionSet( newNeed, std::cerr, 8 );
     501                                )
     502                                inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out );
     503                                return;
     504                        }
     505                }
     506
     507                ForwardIterator cur = begin++;
     508                if ( ! cur->second.isUsed ) {
     509                        inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out );
     510                        return; // xxx - should this continue? previously this wasn't here, and it looks like it should be
     511                }
     512                DeclarationWithType *curDecl = cur->first;
     513
     514                PRINT(
     515                        std::cerr << "inferRecursive: assertion is ";
     516                        curDecl->print( std::cerr );
     517                        std::cerr << std::endl;
     518                )
     519                std::list< SymTab::Indexer::IdData > candidates;
     520                decls.lookupId( curDecl->get_name(), candidates );
     521///   if ( candidates.empty() ) { std::cerr << "no candidates!" << std::endl; }
     522                for ( const auto & data : candidates ) {
     523                        DeclarationWithType * candidate = data.id;
     524                        PRINT(
     525                                std::cerr << "inferRecursive: candidate is ";
     526                                candidate->print( std::cerr );
     527                                std::cerr << std::endl;
     528                        )
     529
     530                        AssertionSet newHave, newerNeed( newNeed );
     531                        TypeEnvironment newEnv( newAlt.env );
     532                        OpenVarSet newOpenVars( openVars );
     533                        Type *adjType = candidate->get_type()->clone();
     534                        adjustExprType( adjType, newEnv, indexer );
     535                        renameTyVars( adjType );
     536                        PRINT(
     537                                std::cerr << "unifying ";
     538                                curDecl->get_type()->print( std::cerr );
     539                                std::cerr << " with ";
     540                                adjType->print( std::cerr );
     541                                std::cerr << std::endl;
     542                        )
     543                        if ( unify( curDecl->get_type(), adjType, newEnv, newerNeed, newHave, newOpenVars, indexer ) ) {
     544                                PRINT(
     545                                        std::cerr << "success!" << std::endl;
     546                                )
     547                                SymTab::Indexer newDecls( decls );
     548                                addToIndexer( newHave, newDecls );
     549                                Alternative newerAlt( newAlt );
     550                                newerAlt.env = newEnv;
     551                                assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
     552
     553                                // everything with an empty idChain was pulled in by the current assertion.
     554                                // add current assertion's idChain + current assertion's ID so that the correct inferParameters can be found.
     555                                for ( auto & a : newerNeed ) {
     556                                        if ( a.second.idChain.empty() ) {
     557                                                a.second.idChain = cur->second.idChain;
     558                                                a.second.idChain.push_back( curDecl->get_uniqueId() );
     559                                        }
     560                                }
     561
     562                                Expression *varExpr = data.combine( newerAlt.cvtCost );
     563                                delete varExpr->get_result();
     564                                varExpr->set_result( adjType->clone() );
     565                                PRINT(
     566                                        std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " ";
     567                                        curDecl->print( std::cerr );
     568                                        std::cerr << " with declaration " << candidate->get_uniqueId() << " ";
     569                                        candidate->print( std::cerr );
     570                                        std::cerr << std::endl;
     571                                )
     572                                // follow the current assertion's ID chain to find the correct set of inferred parameters to add the candidate to (i.e. the set of inferred parameters belonging to the entity which requested the assertion parameter).
     573                                InferredParams * inferParameters = &newerAlt.expr->get_inferParams();
     574                                for ( UniqueId id : cur->second.idChain ) {
     575                                        inferParameters = (*inferParameters)[ id ].inferParams.get();
     576                                }
     577                                // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions
     578                                (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );
     579                                inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out );
     580                        } else {
     581                                delete adjType;
     582                        }
     583                }
     584        }
    505585
    506586        template< typename OutputIterator >
    507         void AlternativeFinder::Finder::inferParameters( Alternative &newAlt, OutputIterator out ) {
    508                 // Set need bindings for any unbound assertions
    509                 UniqueId crntResnSlot = 0;  // matching ID for this expression's assertions
    510                 for ( auto& assn : newAlt.need ) {
    511                         // skip already-matched assertions
    512                         if ( assn.info.resnSlot != 0 ) continue;
    513                         // assign slot for expression if needed
    514                         if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; }
    515                         // fix slot to assertion
    516                         assn.info.resnSlot = crntResnSlot;
    517                 }
    518                 // pair slot to expression
    519                 if ( crntResnSlot != 0 ) { newAlt.expr->resnSlots.push_back( crntResnSlot ); }
    520 
    521                 // add to output list, assertion resolution is deferred
    522                 *out++ = newAlt;
     587        void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {
     588//      PRINT(
     589//          std::cerr << "inferParameters: assertions needed are" << std::endl;
     590//          printAll( need, std::cerr, 8 );
     591//          )
     592                SymTab::Indexer decls( indexer );
     593                // PRINT(
     594                //      std::cerr << "============= original indexer" << std::endl;
     595                //      indexer.print( std::cerr );
     596                //      std::cerr << "============= new indexer" << std::endl;
     597                //      decls.print( std::cerr );
     598                // )
     599                addToIndexer( have, decls );
     600                AssertionSet newNeed;
     601                PRINT(
     602                        std::cerr << "env is: " << std::endl;
     603                        newAlt.env.print( std::cerr, 0 );
     604                        std::cerr << std::endl;
     605                )
     606
     607                inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out );
     608//      PRINT(
     609//          std::cerr << "declaration 14 is ";
     610//          Declaration::declFromId
     611//          *out++ = newAlt;
     612//          )
    523613        }
    524614
     
    861951                }
    862952                // build and validate new alternative
    863                 Alternative newAlt{ appExpr, result.env, result.openVars, result.need, cost };
     953                Alternative newAlt( appExpr, result.env, cost );
    864954                PRINT(
    865955                        std::cerr << "instantiate function success: " << appExpr << std::endl;
     
    867957                        printAssertionSet( result.need, std::cerr, 8 );
    868958                )
    869                 inferParameters( newAlt, out );
     959                inferParameters( result.need, result.have, newAlt, result.openVars, out );
    870960        }
    871961
     
    11121202
    11131203                // function may return struct or union value, in which case we need to add alternatives
    1114                 // for implicit conversions to each of the anonymous members, must happen after findMinCost
     1204                // for implicitconversions to each of the anonymous members, must happen after findMinCost
    11151205                // since anon conversions are never the cheapest expression
    11161206                for ( const Alternative & alt : winners ) {
     
    11441234                        if ( isLvalue( alt.expr ) ) {
    11451235                                alternatives.push_back(
    1146                                         Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } );
     1236                                        Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } );
    11471237                        } // if
    11481238                } // for
     
    11501240
    11511241        void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) {
    1152                 alternatives.push_back( Alternative{ expr->clone(), env } );
     1242                alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } );
    11531243        }
    11541244
     
    11951285                AltList candidates;
    11961286                for ( Alternative & alt : finder.alternatives ) {
    1197                         AssertionSet needAssertions( alt.need.begin(), alt.need.end() );
    1198                         AssertionSet haveAssertions;
    1199                         OpenVarSet openVars{ alt.openVars };
     1287                        AssertionSet needAssertions, haveAssertions;
     1288                        OpenVarSet openVars;
    12001289
    12011290                        alt.env.extractOpenVars( openVars );
     
    12251314                                // count one safe conversion for each value that is thrown away
    12261315                                thisCost.incSafe( discardedValues );
    1227                                 Alternative newAlt{
    1228                                         restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ),
    1229                                         alt.env, openVars, needAssertions, alt.cost, alt.cost + thisCost };
    1230                                 inferParameters( newAlt, back_inserter( candidates ) );
     1316                                Alternative newAlt( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env,
     1317                                        alt.cost, thisCost );
     1318                                inferParameters( needAssertions, haveAssertions, newAlt, openVars,
     1319                                        back_inserter( candidates ) );
    12311320                        } // if
    12321321                } // for
     
    12411330
    12421331        void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) {
    1243                 assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." );
     1332                assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." );
    12441333                AlternativeFinder finder( indexer, env );
    12451334                // don't prune here, since it's guaranteed all alternatives will have the same type
    12461335                finder.findWithoutPrune( castExpr->get_arg() );
    12471336                for ( Alternative & alt : finder.alternatives ) {
    1248                         alternatives.push_back( Alternative{
    1249                                 alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() },
    1250                                 alt.cost } );
     1337                        alternatives.push_back( Alternative(
     1338                                new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ),
     1339                                alt.env, alt.cost ) );
    12511340                }
    12521341        }
     
    12551344                /// Gets name from untyped member expression (member must be NameExpr)
    12561345                const std::string& get_member_name( UntypedMemberExpr *memberExpr ) {
    1257                         if ( dynamic_cast< ConstantExpr * >( memberExpr->get_member() ) ) {
    1258                                 SemanticError( memberExpr, "Indexed access to struct fields unsupported: " );
    1259                         } // if
    12601346                        NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() );
    12611347                        assert( nameExpr );
     
    12761362                        // find member of the given type
    12771363                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    1278                                 addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
     1364                                addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
    12791365                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    1280                                 addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
     1366                                addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
    12811367                        } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
    1282                                 addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() );
     1368                                addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );
    12831369                        } // if
    12841370                } // for
     
    12861372
    12871373        void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) {
    1288                 alternatives.push_back( Alternative{ memberExpr->clone(), env } );
     1374                alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) );
    12891375        }
    12901376
     
    12991385                        // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    13001386                        // can't construct in place and use vector::back
    1301                         Alternative newAlt{ newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost };
     1387                        Alternative newAlt( newExpr, env, Cost::zero, cost );
    13021388                        PRINT(
    13031389                                std::cerr << "decl is ";
     
    13171403                // not sufficient to clone here, because variable's type may have changed
    13181404                // since the VariableExpr was originally created.
    1319                 alternatives.push_back( Alternative{ new VariableExpr{ variableExpr->var }, env } );
     1405                alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) );
    13201406        }
    13211407
    13221408        void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) {
    1323                 alternatives.push_back( Alternative{ constantExpr->clone(), env } );
     1409                alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) );
    13241410        }
    13251411
     
    13271413                if ( sizeofExpr->get_isType() ) {
    13281414                        Type * newType = sizeofExpr->get_type()->clone();
    1329                         alternatives.push_back( Alternative{
    1330                                 new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } );
     1415                        alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
    13311416                } else {
    13321417                        // find all alternatives for the argument to sizeof
     
    13421427                        Alternative &choice = winners.front();
    13431428                        referenceToRvalueConversion( choice.expr, choice.cost );
    1344                         alternatives.push_back( Alternative{
    1345                                 choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } );
     1429                        alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    13461430                } // if
    13471431        }
     
    13501434                if ( alignofExpr->get_isType() ) {
    13511435                        Type * newType = alignofExpr->get_type()->clone();
    1352                         alternatives.push_back( Alternative{
    1353                                 new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } );
     1436                        alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
    13541437                } else {
    13551438                        // find all alternatives for the argument to sizeof
     
    13651448                        Alternative &choice = winners.front();
    13661449                        referenceToRvalueConversion( choice.expr, choice.cost );
    1367                         alternatives.push_back( Alternative{
    1368                                 choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } );
     1450                        alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    13691451                } // if
    13701452        }
     
    13761458                for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    13771459                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
    1378                                 alternatives.push_back( Alternative{
    1379                                         new OffsetofExpr{ aggInst->clone(), dwt }, env } );
     1460                                alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) );
    13801461                                renameTypes( alternatives.back().expr );
    13811462                        } else {
     
    13961477
    13971478        void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) {
    1398                 alternatives.push_back( Alternative{ offsetofExpr->clone(), env } );
     1479                alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) );
    13991480        }
    14001481
    14011482        void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) {
    1402                 alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } );
     1483                alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) );
    14031484        }
    14041485
     
    14201501                                Cost cost = Cost::zero;
    14211502                                Expression * newExpr = data.combine( cost );
    1422                                 alternatives.push_back( Alternative{
    1423                                         new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{},
    1424                                         AssertionList{}, Cost::zero, cost } );
     1503                                alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) );
    14251504                                for ( DeclarationWithType * retVal : function->returnVals ) {
    14261505                                        alternatives.back().expr->result = retVal->get_type()->clone();
     
    14611540                                Cost cost = Cost::zero;
    14621541                                Expression * newExpr = data.combine( cost );
    1463                                 alternatives.push_back( Alternative{
    1464                                         newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost } );
     1542                                alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) );
    14651543                                renameTypes( alternatives.back().expr );
    14661544                        } // for
     
    14771555                for ( const Alternative & first : firstFinder.alternatives ) {
    14781556                        for ( const Alternative & second : secondFinder.alternatives ) {
    1479                                 TypeEnvironment compositeEnv{ first.env };
     1557                                TypeEnvironment compositeEnv;
     1558                                compositeEnv.simpleCombine( first.env );
    14801559                                compositeEnv.simpleCombine( second.env );
    1481                                 OpenVarSet openVars{ first.openVars };
    1482                                 mergeOpenVars( openVars, second.openVars );
    1483                                 AssertionSet need;
    1484                                 cloneAll( first.need, need );
    1485                                 cloneAll( second.need, need );
    1486 
    1487                                 LogicalExpr *newExpr = new LogicalExpr{
    1488                                         first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() };
    1489                                 alternatives.push_back( Alternative{
    1490                                         newExpr, std::move(compositeEnv), std::move(openVars),
    1491                                         AssertionList( need.begin(), need.end() ), first.cost + second.cost } );
     1560
     1561                                LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() );
     1562                                alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) );
    14921563                        }
    14931564                }
     
    15101581                        for ( const Alternative & second : secondFinder.alternatives ) {
    15111582                                for ( const Alternative & third : thirdFinder.alternatives ) {
    1512                                         TypeEnvironment compositeEnv{ first.env };
     1583                                        TypeEnvironment compositeEnv;
     1584                                        compositeEnv.simpleCombine( first.env );
    15131585                                        compositeEnv.simpleCombine( second.env );
    15141586                                        compositeEnv.simpleCombine( third.env );
    1515                                         OpenVarSet openVars{ first.openVars };
    1516                                         mergeOpenVars( openVars, second.openVars );
    1517                                         mergeOpenVars( openVars, third.openVars );
    1518                                         AssertionSet need;
    1519                                         cloneAll( first.need, need );
    1520                                         cloneAll( second.need, need );
    1521                                         cloneAll( third.need, need );
    1522                                         AssertionSet have;
    1523                                        
     1587
    15241588                                        // unify true and false types, then infer parameters to produce new alternatives
     1589                                        OpenVarSet openVars;
     1590                                        AssertionSet needAssertions, haveAssertions;
     1591                                        Alternative newAlt( 0, compositeEnv, first.cost + second.cost + third.cost );
    15251592                                        Type* commonType = nullptr;
    1526                                         if ( unify( second.expr->result, third.expr->result, compositeEnv,
    1527                                                         need, have, openVars, indexer, commonType ) ) {
    1528                                                 ConditionalExpr *newExpr = new ConditionalExpr{
    1529                                                         first.expr->clone(), second.expr->clone(), third.expr->clone() };
     1593                                        if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
     1594                                                ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() );
    15301595                                                newExpr->result = commonType ? commonType : second.expr->result->clone();
    15311596                                                // convert both options to the conditional result type
    1532                                                 Cost cost = first.cost + second.cost + third.cost;
    1533                                                 cost += computeExpressionConversionCost(
    1534                                                         newExpr->arg2, newExpr->result, indexer, compositeEnv );
    1535                                                 cost += computeExpressionConversionCost(
    1536                                                         newExpr->arg3, newExpr->result, indexer, compositeEnv );
    1537                                                 // output alternative
    1538                                                 Alternative newAlt{
    1539                                                         newExpr, std::move(compositeEnv), std::move(openVars),
    1540                                                         AssertionList( need.begin(), need.end() ), cost };
    1541                                                 inferParameters( newAlt, back_inserter( alternatives ) );
     1597                                                newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env );
     1598                                                newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env );
     1599                                                newAlt.expr = newExpr;
     1600                                                inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
    15421601                                        } // if
    15431602                                } // for
     
    15521611                secondFinder.findWithAdjustment( commaExpr->get_arg2() );
    15531612                for ( const Alternative & alt : secondFinder.alternatives ) {
    1554                         alternatives.push_back( Alternative{
    1555                                 alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } );
     1613                        alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) );
    15561614                } // for
    15571615                delete newFirstArg;
     
    15681626                for ( const Alternative & first : firstFinder.alternatives ) {
    15691627                        for ( const Alternative & second : secondFinder.alternatives ) {
    1570                                 TypeEnvironment compositeEnv{ first.env };
     1628                                TypeEnvironment compositeEnv;
     1629                                compositeEnv.simpleCombine( first.env );
    15711630                                compositeEnv.simpleCombine( second.env );
    1572                                 OpenVarSet openVars{ first.openVars };
    1573                                 mergeOpenVars( openVars, second.openVars );
    1574                                 AssertionSet need;
    1575                                 cloneAll( first.need, need );
    1576                                 cloneAll( second.need, need );
    1577                                 AssertionSet have;
    1578 
     1631                                OpenVarSet openVars;
     1632                                AssertionSet needAssertions, haveAssertions;
     1633                                Alternative newAlt( 0, compositeEnv, first.cost + second.cost );
    15791634                                Type* commonType = nullptr;
    1580                                 if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have,
    1581                                                 openVars, indexer, commonType ) ) {
    1582                                         RangeExpr * newExpr =
    1583                                                 new RangeExpr{ first.expr->clone(), second.expr->clone() };
     1635                                if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
     1636                                        RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() );
    15841637                                        newExpr->result = commonType ? commonType : first.expr->result->clone();
    1585                                         Alternative newAlt{
    1586                                                 newExpr, std::move(compositeEnv), std::move(openVars),
    1587                                                 AssertionList( need.begin(), need.end() ), first.cost + second.cost };
    1588                                         inferParameters( newAlt, back_inserter( alternatives ) );
     1638                                        newAlt.expr = newExpr;
     1639                                        inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
    15891640                                } // if
    15901641                        } // for
     
    16041655
    16051656                        TypeEnvironment compositeEnv;
    1606                         OpenVarSet openVars;
    1607                         AssertionSet need;
    1608                         for ( const Alternative& alt : alts ) {
    1609                                 compositeEnv.simpleCombine( alt.env );
    1610                                 mergeOpenVars( openVars, alt.openVars );
    1611                                 cloneAll( alt.need, need );
    1612                         }
    1613                        
    1614                         alternatives.push_back( Alternative{
    1615                                 new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars),
    1616                                 AssertionList( need.begin(), need.end() ), sumCost( alts ) } );
     1657                        simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv );
     1658                        alternatives.push_back(
     1659                                Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } );
    16171660                } // for
    16181661        }
    16191662
    16201663        void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) {
    1621                 alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
     1664                alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    16221665        }
    16231666
    16241667        void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    1625                 alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } );
     1668                alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );
    16261669        }
    16271670
     
    16321675                finder.findWithoutPrune( ctorExpr->get_callExpr() );
    16331676                for ( Alternative & alt : finder.alternatives ) {
    1634                         alternatives.push_back( Alternative{
    1635                                 alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } );
     1677                        alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) );
    16361678                }
    16371679        }
    16381680
    16391681        void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) {
    1640                 alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
     1682                alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    16411683        }
    16421684
    16431685        void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) {
    1644                 alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } );
     1686                alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) );
    16451687        }
    16461688
     
    16511693                        // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked"
    16521694                        UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() );
    1653                         alternatives.push_back( Alternative{ alt, newUnqExpr, alt.cost } );
     1695                        alternatives.push_back( Alternative( newUnqExpr, alt.env, alt.cost ) );
    16541696                }
    16551697        }
     
    16591701                ResolvExpr::resolveStmtExpr( newStmtExpr, indexer );
    16601702                // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr...
    1661                 alternatives.push_back( Alternative{ newStmtExpr, env } );
     1703                alternatives.push_back( Alternative( newStmtExpr, env, Cost::zero ) );
    16621704        }
    16631705
     
    16811723                        for ( Alternative & alt : finder.get_alternatives() ) {
    16821724                                TypeEnvironment newEnv( alt.env );
    1683                                 AssertionSet need;
    1684                                 cloneAll( alt.need, need );
    1685                                 AssertionSet have;
    1686                                 OpenVarSet openVars( alt.openVars ); 
    1687                                 // xxx - find things in env that don't have a "representative type" and claim
    1688                                 // those are open vars?
     1725                                AssertionSet needAssertions, haveAssertions;
     1726                                OpenVarSet openVars;  // find things in env that don't have a "representative type" and claim those are open vars?
    16891727                                PRINT(
    16901728                                        std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
    16911729                                )
    1692                                 // It's possible that a cast can throw away some values in a multiply-valued
    1693                                 // expression. (An example is a cast-to-void, which casts from one value to
    1694                                 // zero.)  Figure out the prefix of the subexpression results that are cast
    1695                                 // directly.  The candidate is invalid if it has fewer results than there are
    1696                                 // types to cast to.
     1730                                // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
     1731                                // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
     1732                                // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
     1733                                // to.
    16971734                                int discardedValues = alt.expr->result->size() - toType->size();
    16981735                                if ( discardedValues < 0 ) continue;
    1699                                 // xxx - may need to go into tuple types and extract relevant types and use
    1700                                 // unifyList. Note that currently, this does not allow casting a tuple to an
    1701                                 // atomic type (e.g. (int)([1, 2, 3]))
    1702                                
     1736                                // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
     1737                                // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    17031738                                // unification run for side-effects
    1704                                 unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer );
    1705                                 // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?
     1739                                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??
    17061740
    17071741                                Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv );
     
    17091743                                        // count one safe conversion for each value that is thrown away
    17101744                                        thisCost.incSafe( discardedValues );
    1711                                         Alternative newAlt{
    1712                                                 new InitExpr{
    1713                                                         restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() },
    1714                                                 std::move(newEnv), std::move(openVars),
    1715                                                 AssertionList( need.begin(), need.end() ), alt.cost, thisCost };
    1716                                         inferParameters( newAlt, back_inserter( candidates ) );
     1745                                        Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost );
     1746                                        inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
    17171747                                }
    17181748                        }
Note: See TracChangeset for help on using the changeset viewer.