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

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

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