Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    rd97c3a4 r30ee9efc  
    1111// Last Modified By : Peter A. Buhr
    1212// Last Modified On : Thu Nov  1 21:00:56 2018
    13 // Update Count     : 35
     13// Update Count     : 34
    1414//
    1515
     
    3434#include "InitTweak/InitTweak.h"   // for getFunctionName
    3535#include "RenameVars.h"            // for RenameVars, global_renamer
    36 #include "ResolveAssertions.h"     // for resolveAssertions
    3736#include "ResolveTypeof.h"         // for resolveTypeof
    3837#include "Resolver.h"              // for resolveStmtExpr
     
    103102                void addAnonConversions( const Alternative & alt );
    104103                /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
    105                 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative &alt, const Cost &newCost, const std::string & name );
     104                template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name );
    106105                /// Adds alternatives for member expressions where the left side has tuple type
    107                 void addTupleMembers( TupleType *tupleType, Expression *expr, const Alternative &alt, const Cost &newCost, Expression *member );
     106                void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
    108107                /// Adds alternatives for offsetof expressions, given the base type and name of the member
    109108                template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
     
    114113                template<typename OutputIterator>
    115114                void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out );
    116                 /// Sets up parameter inference for an output alternative
     115                /// Checks if assertion parameters match for a new alternative
    117116                template< typename OutputIterator >
    118                 void inferParameters( Alternative &newAlt, OutputIterator out );
     117                void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
    119118        private:
    120119                AlternativeFinder & altFinder;
     
    245244        }
    246245
    247         void AlternativeFinder::find( Expression *expr, ResolvMode mode ) {
     246        void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) {
    248247                PassVisitor<Finder> finder( *this );
    249248                expr->accept( finder );
    250                 if ( mode.failFast && alternatives.empty() ) {
     249                if ( failFast && alternatives.empty() ) {
    251250                        PRINT(
    252251                                std::cerr << "No reasonable alternatives for expression " << expr << std::endl;
     
    254253                        SemanticError( expr, "No reasonable alternatives for expression " );
    255254                }
    256                 if ( mode.resolveAssns || mode.prune ) {
    257                         // trim candidates just to those where the assertions resolve
    258                         // - necessary pre-requisite to pruning
    259                         AltList candidates;
    260                         for ( unsigned i = 0; i < alternatives.size(); ++i ) {
    261                                 resolveAssertions( alternatives[i], indexer, candidates );
    262                         }
    263                         // fail early if none such
    264                         if ( mode.failFast && candidates.empty() ) {
    265                                 std::ostringstream stream;
    266                                 stream << "No resolvable alternatives for expression " << expr << "\n"
    267                                        << "Alternatives with failing assertions are:\n";
    268                                 printAlts( alternatives, stream, 1 );
    269                                 SemanticError( expr->location, stream.str() );
    270                         }
    271                         // reset alternatives
    272                         alternatives = std::move( candidates );
    273                 }
    274                 if ( mode.prune ) {
     255                if ( prune ) {
    275256                        auto oldsize = alternatives.size();
    276257                        PRINT(
     
    280261                        AltList pruned;
    281262                        pruneAlternatives( alternatives.begin(), alternatives.end(), back_inserter( pruned ) );
    282                         if ( mode.failFast && pruned.empty() ) {
     263                        if ( failFast && pruned.empty() ) {
    283264                                std::ostringstream stream;
    284265                                AltList winners;
     
    299280                }
    300281                // adjust types after pruning so that types substituted by pruneAlternatives are correctly adjusted
    301                 if ( mode.adjust ) {
    302                         for ( Alternative& i : alternatives ) {
    303                                 adjustExprType( i.expr->get_result(), i.env, indexer );
     282                for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
     283                        if ( adjust ) {
     284                                adjustExprType( i->expr->get_result(), i->env, indexer );
    304285                        }
    305286                }
     
    313294
    314295        void AlternativeFinder::findWithAdjustment( Expression *expr ) {
    315                 find( expr, ResolvMode::withAdjustment() );
     296                find( expr, true );
    316297        }
    317298
    318299        void AlternativeFinder::findWithoutPrune( Expression * expr ) {
    319                 find( expr, ResolvMode::withoutPrune() );
     300                find( expr, true, false );
    320301        }
    321302
    322303        void AlternativeFinder::maybeFind( Expression * expr ) {
    323                 find( expr, ResolvMode::withoutFailFast() );
     304                find( expr, true, true, false );
    324305        }
    325306
     
    336317
    337318                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
    338                         addAggMembers( structInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
     319                        addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
    339320                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
    340                         addAggMembers( unionInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
     321                        addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
    341322                } // if
    342323        }
    343324
    344325        template< typename StructOrUnionType >
    345         void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative& alt, const Cost &newCost, const std::string & name ) {
     326        void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) {
    346327                std::list< Declaration* > members;
    347328                aggInst->lookup( name, members );
     
    351332                                // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    352333                                // can't construct in place and use vector::back
    353                                 Alternative newAlt{ alt, new MemberExpr{ dwt, expr->clone() }, newCost };
     334                                Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost );
    354335                                renameTypes( newAlt.expr );
    355336                                addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
     
    361342        }
    362343
    363         void AlternativeFinder::Finder::addTupleMembers( TupleType *tupleType, Expression *expr,                        const Alternative &alt, const Cost &newCost, Expression *member ) {
     344        void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    364345                if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
    365346                        // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
     
    367348                        std::string tmp;
    368349                        if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    369                                 alternatives.push_back( Alternative{
    370                                         alt, new TupleIndexExpr( expr->clone(), val ), newCost } );
     350                                alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
    371351                        } // if
    372352                } // if
     
    374354
    375355        void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) {
    376                 alternatives.push_back( Alternative{ applicationExpr->clone(), env } );
     356                alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) );
    377357        }
    378358
     
    430410        Cost computeApplicationConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
    431411                ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( alt.expr );
    432                 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result );
    433                 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base );
     412                PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
     413                FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() );
    434414
    435415                Cost convCost = Cost::zero;
    436                 std::list< DeclarationWithType* >& formals = function->parameters;
     416                std::list< DeclarationWithType* >& formals = function->get_parameters();
    437417                std::list< DeclarationWithType* >::iterator formal = formals.begin();
    438                 std::list< Expression* >& actuals = appExpr->args;
    439 
    440                 for ( Expression*& actualExpr : actuals ) {
    441                         Type * actualType = actualExpr->result;
     418                std::list< Expression* >& actuals = appExpr->get_args();
     419
     420                for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
     421                        Type * actualType = (*actualExpr)->get_result();
    442422                        PRINT(
    443423                                std::cerr << "actual expression:" << std::endl;
    444                                 actualExpr->print( std::cerr, 8 );
     424                                (*actualExpr)->print( std::cerr, 8 );
    445425                                std::cerr << "--- results are" << std::endl;
    446426                                actualType->print( std::cerr, 8 );
    447427                        )
    448428                        if ( formal == formals.end() ) {
    449                                 if ( function->isVarArgs ) {
     429                                if ( function->get_isVarArgs() ) {
    450430                                        convCost.incUnsafe();
    451431                                        PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; )
    452432                                        // convert reference-typed expressions to value-typed expressions
    453                                         referenceToRvalueConversion( actualExpr, convCost );
     433                                        referenceToRvalueConversion( *actualExpr, convCost );
    454434                                        continue;
    455435                                } else {
     
    457437                                }
    458438                        }
    459                         if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( actualExpr ) ) {
     439                        if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) {
    460440                                // default arguments should be free - don't include conversion cost.
    461441                                // Unwrap them here because they are not relevant to the rest of the system.
    462                                 actualExpr = def->expr;
     442                                *actualExpr = def->expr;
    463443                                ++formal;
    464444                                continue;
    465445                        }
    466                         // mark conversion cost to formal and also specialization cost of formal type
    467446                        Type * formalType = (*formal)->get_type();
    468                         convCost += computeExpressionConversionCost( actualExpr, formalType, indexer, alt.env );
    469                         convCost.decSpec( specCost( formalType ) );
     447                        convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env );
    470448                        ++formal; // can't be in for-loop update because of the continue
    471449                }
     
    474452                }
    475453
    476                 // mark specialization cost of return types
    477                 for ( DeclarationWithType* returnVal : function->returnVals ) {
    478                         convCost.decSpec( specCost( returnVal->get_type() ) );
    479                 }
    480 
    481                 // mark type variable and specialization cost of forall clause
    482                 convCost.incVar( function->forall.size() );
    483                 for ( TypeDecl* td : function->forall ) {
    484                         convCost.decSpec( td->assertions.size() );
    485                 }
    486 
    487                 // xxx -- replace with new costs in resolver
    488                 for ( InferredParams::const_iterator assert = appExpr->inferParams.begin(); assert != appExpr->inferParams.end(); ++assert ) {
     454                for ( InferredParams::const_iterator assert = appExpr->get_inferParams().begin(); assert != appExpr->get_inferParams().end(); ++assert ) {
    489455                        convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env );
    490456                }
     
    500466                                needAssertions[ *assert ].isUsed = true;
    501467                        }
    502                 }
    503         }
    504 
    505         /// Unique identifier for matching expression resolutions to their requesting expression
    506         UniqueId globalResnSlot = 0;
     468///     needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() );
     469                }
     470        }
     471
     472        static const int recursionLimit = /*10*/ 4;  ///< Limit to depth of recursion satisfaction
     473
     474        void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) {
     475                for ( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i ) {
     476                        if ( i->second.isUsed ) {
     477                                indexer.addId( i->first );
     478                        }
     479                }
     480        }
     481
     482        template< typename ForwardIterator, typename OutputIterator >
     483        void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, int level, const SymTab::Indexer &indexer, OutputIterator out ) {
     484                if ( newAlt.cost == Cost::infinity ) return; // don't proceed down this dead end
     485                if ( begin == end ) {
     486                        if ( newNeed.empty() ) {
     487                                PRINT(
     488                                        std::cerr << "all assertions satisfied, output alternative: ";
     489                                        newAlt.print( std::cerr );
     490                                        std::cerr << std::endl;
     491                                );
     492                                *out++ = newAlt;
     493                                return;
     494                        } else if ( level >= recursionLimit ) {
     495                                SemanticError( newAlt.expr->location, "Too many recursive assertions" );
     496                        } else {
     497                                AssertionSet newerNeed;
     498                                PRINT(
     499                                        std::cerr << "recursing with new set:" << std::endl;
     500                                        printAssertionSet( newNeed, std::cerr, 8 );
     501                                )
     502                                inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out );
     503                                return;
     504                        }
     505                }
     506
     507                ForwardIterator cur = begin++;
     508                if ( ! cur->second.isUsed ) {
     509                        inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out );
     510                        return; // xxx - should this continue? previously this wasn't here, and it looks like it should be
     511                }
     512                DeclarationWithType *curDecl = cur->first;
     513
     514                PRINT(
     515                        std::cerr << "inferRecursive: assertion is ";
     516                        curDecl->print( std::cerr );
     517                        std::cerr << std::endl;
     518                )
     519                std::list< SymTab::Indexer::IdData > candidates;
     520                decls.lookupId( curDecl->get_name(), candidates );
     521///   if ( candidates.empty() ) { std::cerr << "no candidates!" << std::endl; }
     522                for ( const auto & data : candidates ) {
     523                        DeclarationWithType * candidate = data.id;
     524                        PRINT(
     525                                std::cerr << "inferRecursive: candidate is ";
     526                                candidate->print( std::cerr );
     527                                std::cerr << std::endl;
     528                        )
     529
     530                        AssertionSet newHave, newerNeed( newNeed );
     531                        TypeEnvironment newEnv( newAlt.env );
     532                        OpenVarSet newOpenVars( openVars );
     533                        Type *adjType = candidate->get_type()->clone();
     534                        adjustExprType( adjType, newEnv, indexer );
     535                        renameTyVars( adjType );
     536                        PRINT(
     537                                std::cerr << "unifying ";
     538                                curDecl->get_type()->print( std::cerr );
     539                                std::cerr << " with ";
     540                                adjType->print( std::cerr );
     541                                std::cerr << std::endl;
     542                        )
     543                        if ( unify( curDecl->get_type(), adjType, newEnv, newerNeed, newHave, newOpenVars, indexer ) ) {
     544                                PRINT(
     545                                        std::cerr << "success!" << std::endl;
     546                                )
     547                                SymTab::Indexer newDecls( decls );
     548                                addToIndexer( newHave, newDecls );
     549                                Alternative newerAlt( newAlt );
     550                                newerAlt.env = newEnv;
     551                                assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
     552
     553                                // everything with an empty idChain was pulled in by the current assertion.
     554                                // add current assertion's idChain + current assertion's ID so that the correct inferParameters can be found.
     555                                for ( auto & a : newerNeed ) {
     556                                        if ( a.second.idChain.empty() ) {
     557                                                a.second.idChain = cur->second.idChain;
     558                                                a.second.idChain.push_back( curDecl->get_uniqueId() );
     559                                        }
     560                                }
     561
     562                                Expression *varExpr = data.combine( newerAlt.cvtCost );
     563                                delete varExpr->get_result();
     564                                varExpr->set_result( adjType->clone() );
     565                                PRINT(
     566                                        std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " ";
     567                                        curDecl->print( std::cerr );
     568                                        std::cerr << " with declaration " << candidate->get_uniqueId() << " ";
     569                                        candidate->print( std::cerr );
     570                                        std::cerr << std::endl;
     571                                )
     572                                // follow the current assertion's ID chain to find the correct set of inferred parameters to add the candidate to (i.e. the set of inferred parameters belonging to the entity which requested the assertion parameter).
     573                                InferredParams * inferParameters = &newerAlt.expr->get_inferParams();
     574                                for ( UniqueId id : cur->second.idChain ) {
     575                                        inferParameters = (*inferParameters)[ id ].inferParams.get();
     576                                }
     577                                // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions
     578                                (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );
     579                                inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out );
     580                        } else {
     581                                delete adjType;
     582                        }
     583                }
     584        }
    507585
    508586        template< typename OutputIterator >
    509         void AlternativeFinder::Finder::inferParameters( Alternative &newAlt, OutputIterator out ) {
    510                 // Set need bindings for any unbound assertions
    511                 UniqueId crntResnSlot = 0;  // matching ID for this expression's assertions
    512                 for ( auto& assn : newAlt.need ) {
    513                         // skip already-matched assertions
    514                         if ( assn.info.resnSlot != 0 ) continue;
    515                         // assign slot for expression if needed
    516                         if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; }
    517                         // fix slot to assertion
    518                         assn.info.resnSlot = crntResnSlot;
    519                 }
    520                 // pair slot to expression
    521                 if ( crntResnSlot != 0 ) { newAlt.expr->resnSlots.push_back( crntResnSlot ); }
    522 
    523                 // add to output list, assertion resolution is deferred
    524                 *out++ = newAlt;
     587        void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {
     588//      PRINT(
     589//          std::cerr << "inferParameters: assertions needed are" << std::endl;
     590//          printAll( need, std::cerr, 8 );
     591//          )
     592                SymTab::Indexer decls( indexer );
     593                // PRINT(
     594                //      std::cerr << "============= original indexer" << std::endl;
     595                //      indexer.print( std::cerr );
     596                //      std::cerr << "============= new indexer" << std::endl;
     597                //      decls.print( std::cerr );
     598                // )
     599                addToIndexer( have, decls );
     600                AssertionSet newNeed;
     601                PRINT(
     602                        std::cerr << "env is: " << std::endl;
     603                        newAlt.env.print( std::cerr, 0 );
     604                        std::cerr << std::endl;
     605                )
     606
     607                inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out );
     608//      PRINT(
     609//          std::cerr << "declaration 14 is ";
     610//          Declaration::declFromId
     611//          *out++ = newAlt;
     612//          )
    525613        }
    526614
     
    863951                }
    864952                // build and validate new alternative
    865                 Alternative newAlt{ appExpr, result.env, result.openVars, result.need, cost };
     953                Alternative newAlt( appExpr, result.env, cost );
    866954                PRINT(
    867955                        std::cerr << "instantiate function success: " << appExpr << std::endl;
     
    869957                        printAssertionSet( result.need, std::cerr, 8 );
    870958                )
    871                 inferParameters( newAlt, out );
     959                inferParameters( result.need, result.have, newAlt, result.openVars, out );
    872960        }
    873961
     
    11141202
    11151203                // function may return struct or union value, in which case we need to add alternatives
    1116                 // for implicit conversions to each of the anonymous members, must happen after findMinCost
     1204                // for implicitconversions to each of the anonymous members, must happen after findMinCost
    11171205                // since anon conversions are never the cheapest expression
    11181206                for ( const Alternative & alt : winners ) {
     
    11461234                        if ( isLvalue( alt.expr ) ) {
    11471235                                alternatives.push_back(
    1148                                         Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } );
     1236                                        Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } );
    11491237                        } // if
    11501238                } // for
     
    11521240
    11531241        void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) {
    1154                 alternatives.push_back( Alternative{ expr->clone(), env } );
     1242                alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } );
    11551243        }
    11561244
     
    11971285                AltList candidates;
    11981286                for ( Alternative & alt : finder.alternatives ) {
    1199                         AssertionSet needAssertions( alt.need.begin(), alt.need.end() );
    1200                         AssertionSet haveAssertions;
    1201                         OpenVarSet openVars{ alt.openVars };
     1287                        AssertionSet needAssertions, haveAssertions;
     1288                        OpenVarSet openVars;
    12021289
    12031290                        alt.env.extractOpenVars( openVars );
     
    12271314                                // count one safe conversion for each value that is thrown away
    12281315                                thisCost.incSafe( discardedValues );
    1229                                 Alternative newAlt{
    1230                                         restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ),
    1231                                         alt.env, openVars, needAssertions, alt.cost + thisCost, thisCost };
    1232                                 inferParameters( newAlt, back_inserter( candidates ) );
     1316                                Alternative newAlt( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env,
     1317                                        alt.cost, thisCost );
     1318                                inferParameters( needAssertions, haveAssertions, newAlt, openVars,
     1319                                        back_inserter( candidates ) );
    12331320                        } // if
    12341321                } // for
     
    12431330
    12441331        void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) {
    1245                 assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." );
     1332                assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." );
    12461333                AlternativeFinder finder( indexer, env );
    12471334                // don't prune here, since it's guaranteed all alternatives will have the same type
    12481335                finder.findWithoutPrune( castExpr->get_arg() );
    12491336                for ( Alternative & alt : finder.alternatives ) {
    1250                         alternatives.push_back( Alternative{
    1251                                 alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() },
    1252                                 alt.cost } );
     1337                        alternatives.push_back( Alternative(
     1338                                new VirtualCastExpr( alt.expr->clone(), castExpr->get_result()->clone() ),
     1339                                alt.env, alt.cost ) );
    12531340                }
    12541341        }
     
    12781365                        // find member of the given type
    12791366                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    1280                                 addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
     1367                                addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
    12811368                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    1282                                 addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
     1369                                addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
    12831370                        } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
    1284                                 addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() );
     1371                                addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );
    12851372                        } // if
    12861373                } // for
     
    12881375
    12891376        void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) {
    1290                 alternatives.push_back( Alternative{ memberExpr->clone(), env } );
     1377                alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) );
    12911378        }
    12921379
     
    13011388                        // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    13021389                        // can't construct in place and use vector::back
    1303                         Alternative newAlt{ newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost };
     1390                        Alternative newAlt( newExpr, env, Cost::zero, cost );
    13041391                        PRINT(
    13051392                                std::cerr << "decl is ";
     
    13191406                // not sufficient to clone here, because variable's type may have changed
    13201407                // since the VariableExpr was originally created.
    1321                 alternatives.push_back( Alternative{ new VariableExpr{ variableExpr->var }, env } );
     1408                alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) );
    13221409        }
    13231410
    13241411        void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) {
    1325                 alternatives.push_back( Alternative{ constantExpr->clone(), env } );
     1412                alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) );
    13261413        }
    13271414
     
    13291416                if ( sizeofExpr->get_isType() ) {
    13301417                        Type * newType = sizeofExpr->get_type()->clone();
    1331                         alternatives.push_back( Alternative{
    1332                                 new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } );
     1418                        alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
    13331419                } else {
    13341420                        // find all alternatives for the argument to sizeof
     
    13441430                        Alternative &choice = winners.front();
    13451431                        referenceToRvalueConversion( choice.expr, choice.cost );
    1346                         alternatives.push_back( Alternative{
    1347                                 choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } );
     1432                        alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    13481433                } // if
    13491434        }
     
    13521437                if ( alignofExpr->get_isType() ) {
    13531438                        Type * newType = alignofExpr->get_type()->clone();
    1354                         alternatives.push_back( Alternative{
    1355                                 new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } );
     1439                        alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
    13561440                } else {
    13571441                        // find all alternatives for the argument to sizeof
     
    13671451                        Alternative &choice = winners.front();
    13681452                        referenceToRvalueConversion( choice.expr, choice.cost );
    1369                         alternatives.push_back( Alternative{
    1370                                 choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } );
     1453                        alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    13711454                } // if
    13721455        }
     
    13781461                for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    13791462                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
    1380                                 alternatives.push_back( Alternative{
    1381                                         new OffsetofExpr{ aggInst->clone(), dwt }, env } );
     1463                                alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) );
    13821464                                renameTypes( alternatives.back().expr );
    13831465                        } else {
     
    13981480
    13991481        void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) {
    1400                 alternatives.push_back( Alternative{ offsetofExpr->clone(), env } );
     1482                alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) );
    14011483        }
    14021484
    14031485        void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) {
    1404                 alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } );
     1486                alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) );
    14051487        }
    14061488
     
    14221504                                Cost cost = Cost::zero;
    14231505                                Expression * newExpr = data.combine( cost );
    1424                                 alternatives.push_back( Alternative{
    1425                                         new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{},
    1426                                         AssertionList{}, Cost::zero, cost } );
     1506                                alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) );
    14271507                                for ( DeclarationWithType * retVal : function->returnVals ) {
    14281508                                        alternatives.back().expr->result = retVal->get_type()->clone();
     
    14631543                                Cost cost = Cost::zero;
    14641544                                Expression * newExpr = data.combine( cost );
    1465                                 alternatives.push_back( Alternative{
    1466                                         newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost } );
     1545                                alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) );
    14671546                                renameTypes( alternatives.back().expr );
    14681547                        } // for
     
    14791558                for ( const Alternative & first : firstFinder.alternatives ) {
    14801559                        for ( const Alternative & second : secondFinder.alternatives ) {
    1481                                 TypeEnvironment compositeEnv{ first.env };
     1560                                TypeEnvironment compositeEnv;
     1561                                compositeEnv.simpleCombine( first.env );
    14821562                                compositeEnv.simpleCombine( second.env );
    1483                                 OpenVarSet openVars{ first.openVars };
    1484                                 mergeOpenVars( openVars, second.openVars );
    1485                                 AssertionSet need;
    1486                                 cloneAll( first.need, need );
    1487                                 cloneAll( second.need, need );
    1488 
    1489                                 LogicalExpr *newExpr = new LogicalExpr{
    1490                                         first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() };
    1491                                 alternatives.push_back( Alternative{
    1492                                         newExpr, std::move(compositeEnv), std::move(openVars),
    1493                                         AssertionList( need.begin(), need.end() ), first.cost + second.cost } );
     1563
     1564                                LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() );
     1565                                alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) );
    14941566                        }
    14951567                }
     
    15121584                        for ( const Alternative & second : secondFinder.alternatives ) {
    15131585                                for ( const Alternative & third : thirdFinder.alternatives ) {
    1514                                         TypeEnvironment compositeEnv{ first.env };
     1586                                        TypeEnvironment compositeEnv;
     1587                                        compositeEnv.simpleCombine( first.env );
    15151588                                        compositeEnv.simpleCombine( second.env );
    15161589                                        compositeEnv.simpleCombine( third.env );
    1517                                         OpenVarSet openVars{ first.openVars };
    1518                                         mergeOpenVars( openVars, second.openVars );
    1519                                         mergeOpenVars( openVars, third.openVars );
    1520                                         AssertionSet need;
    1521                                         cloneAll( first.need, need );
    1522                                         cloneAll( second.need, need );
    1523                                         cloneAll( third.need, need );
    1524                                         AssertionSet have;
    1525                                        
     1590
    15261591                                        // unify true and false types, then infer parameters to produce new alternatives
     1592                                        OpenVarSet openVars;
     1593                                        AssertionSet needAssertions, haveAssertions;
     1594                                        Alternative newAlt( 0, compositeEnv, first.cost + second.cost + third.cost );
    15271595                                        Type* commonType = nullptr;
    1528                                         if ( unify( second.expr->result, third.expr->result, compositeEnv,
    1529                                                         need, have, openVars, indexer, commonType ) ) {
    1530                                                 ConditionalExpr *newExpr = new ConditionalExpr{
    1531                                                         first.expr->clone(), second.expr->clone(), third.expr->clone() };
     1596                                        if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
     1597                                                ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() );
    15321598                                                newExpr->result = commonType ? commonType : second.expr->result->clone();
    15331599                                                // convert both options to the conditional result type
    1534                                                 Cost cost = first.cost + second.cost + third.cost;
    1535                                                 cost += computeExpressionConversionCost(
    1536                                                         newExpr->arg2, newExpr->result, indexer, compositeEnv );
    1537                                                 cost += computeExpressionConversionCost(
    1538                                                         newExpr->arg3, newExpr->result, indexer, compositeEnv );
    1539                                                 // output alternative
    1540                                                 Alternative newAlt{
    1541                                                         newExpr, std::move(compositeEnv), std::move(openVars),
    1542                                                         AssertionList( need.begin(), need.end() ), cost };
    1543                                                 inferParameters( newAlt, back_inserter( alternatives ) );
     1600                                                newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env );
     1601                                                newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env );
     1602                                                newAlt.expr = newExpr;
     1603                                                inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
    15441604                                        } // if
    15451605                                } // for
     
    15541614                secondFinder.findWithAdjustment( commaExpr->get_arg2() );
    15551615                for ( const Alternative & alt : secondFinder.alternatives ) {
    1556                         alternatives.push_back( Alternative{
    1557                                 alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } );
     1616                        alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) );
    15581617                } // for
    15591618                delete newFirstArg;
     
    15701629                for ( const Alternative & first : firstFinder.alternatives ) {
    15711630                        for ( const Alternative & second : secondFinder.alternatives ) {
    1572                                 TypeEnvironment compositeEnv{ first.env };
     1631                                TypeEnvironment compositeEnv;
     1632                                compositeEnv.simpleCombine( first.env );
    15731633                                compositeEnv.simpleCombine( second.env );
    1574                                 OpenVarSet openVars{ first.openVars };
    1575                                 mergeOpenVars( openVars, second.openVars );
    1576                                 AssertionSet need;
    1577                                 cloneAll( first.need, need );
    1578                                 cloneAll( second.need, need );
    1579                                 AssertionSet have;
    1580 
     1634                                OpenVarSet openVars;
     1635                                AssertionSet needAssertions, haveAssertions;
     1636                                Alternative newAlt( 0, compositeEnv, first.cost + second.cost );
    15811637                                Type* commonType = nullptr;
    1582                                 if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have,
    1583                                                 openVars, indexer, commonType ) ) {
    1584                                         RangeExpr * newExpr =
    1585                                                 new RangeExpr{ first.expr->clone(), second.expr->clone() };
     1638                                if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
     1639                                        RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() );
    15861640                                        newExpr->result = commonType ? commonType : first.expr->result->clone();
    1587                                         Alternative newAlt{
    1588                                                 newExpr, std::move(compositeEnv), std::move(openVars),
    1589                                                 AssertionList( need.begin(), need.end() ), first.cost + second.cost };
    1590                                         inferParameters( newAlt, back_inserter( alternatives ) );
     1641                                        newAlt.expr = newExpr;
     1642                                        inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
    15911643                                } // if
    15921644                        } // for
     
    16061658
    16071659                        TypeEnvironment compositeEnv;
    1608                         OpenVarSet openVars;
    1609                         AssertionSet need;
    1610                         for ( const Alternative& alt : alts ) {
    1611                                 compositeEnv.simpleCombine( alt.env );
    1612                                 mergeOpenVars( openVars, alt.openVars );
    1613                                 cloneAll( alt.need, need );
    1614                         }
    1615                        
    1616                         alternatives.push_back( Alternative{
    1617                                 new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars),
    1618                                 AssertionList( need.begin(), need.end() ), sumCost( alts ) } );
     1660                        simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv );
     1661                        alternatives.push_back(
     1662                                Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } );
    16191663                } // for
    16201664        }
    16211665
    16221666        void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) {
    1623                 alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
     1667                alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    16241668        }
    16251669
    16261670        void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    1627                 alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } );
     1671                alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );
    16281672        }
    16291673
     
    16341678                finder.findWithoutPrune( ctorExpr->get_callExpr() );
    16351679                for ( Alternative & alt : finder.alternatives ) {
    1636                         alternatives.push_back( Alternative{
    1637                                 alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } );
     1680                        alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) );
    16381681                }
    16391682        }
    16401683
    16411684        void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) {
    1642                 alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
     1685                alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    16431686        }
    16441687
    16451688        void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) {
    1646                 alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } );
     1689                alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) );
    16471690        }
    16481691
     
    16531696                        // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked"
    16541697                        UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() );
    1655                         alternatives.push_back( Alternative{ alt, newUnqExpr, alt.cost } );
     1698                        alternatives.push_back( Alternative( newUnqExpr, alt.env, alt.cost ) );
    16561699                }
    16571700        }
     
    16611704                ResolvExpr::resolveStmtExpr( newStmtExpr, indexer );
    16621705                // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr...
    1663                 alternatives.push_back( Alternative{ newStmtExpr, env } );
     1706                alternatives.push_back( Alternative( newStmtExpr, env, Cost::zero ) );
    16641707        }
    16651708
     
    16831726                        for ( Alternative & alt : finder.get_alternatives() ) {
    16841727                                TypeEnvironment newEnv( alt.env );
    1685                                 AssertionSet need;
    1686                                 cloneAll( alt.need, need );
    1687                                 AssertionSet have;
    1688                                 OpenVarSet openVars( alt.openVars ); 
    1689                                 // xxx - find things in env that don't have a "representative type" and claim
    1690                                 // those are open vars?
     1728                                AssertionSet needAssertions, haveAssertions;
     1729                                OpenVarSet openVars;  // find things in env that don't have a "representative type" and claim those are open vars?
    16911730                                PRINT(
    16921731                                        std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
    16931732                                )
    1694                                 // It's possible that a cast can throw away some values in a multiply-valued
    1695                                 // expression. (An example is a cast-to-void, which casts from one value to
    1696                                 // zero.)  Figure out the prefix of the subexpression results that are cast
    1697                                 // directly.  The candidate is invalid if it has fewer results than there are
    1698                                 // types to cast to.
     1733                                // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
     1734                                // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
     1735                                // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
     1736                                // to.
    16991737                                int discardedValues = alt.expr->result->size() - toType->size();
    17001738                                if ( discardedValues < 0 ) continue;
    1701                                 // xxx - may need to go into tuple types and extract relevant types and use
    1702                                 // unifyList. Note that currently, this does not allow casting a tuple to an
    1703                                 // atomic type (e.g. (int)([1, 2, 3]))
    1704                                
     1739                                // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
     1740                                // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    17051741                                // unification run for side-effects
    1706                                 unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer );
    1707                                 // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?
     1742                                unify( toType, alt.expr->result, newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type??
    17081743
    17091744                                Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv );
     
    17111746                                        // count one safe conversion for each value that is thrown away
    17121747                                        thisCost.incSafe( discardedValues );
    1713                                         Alternative newAlt{
    1714                                                 new InitExpr{
    1715                                                         restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() },
    1716                                                 std::move(newEnv), std::move(openVars),
    1717                                                 AssertionList( need.begin(), need.end() ), alt.cost, thisCost };
    1718                                         inferParameters( newAlt, back_inserter( candidates ) );
     1748                                        Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost );
     1749                                        inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
    17191750                                }
    17201751                        }
Note: See TracChangeset for help on using the changeset viewer.