Ignore:
Timestamp:
Jan 23, 2019, 4:52:16 PM (7 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
a200795
Parents:
9b086ca (diff), 1d832f4 (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' into cleanup-dtors

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AlternativeFinder.cc

    r9b086ca rcde3891  
    1010// Created On       : Sat May 16 23:52:08 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Feb 17 11:19:39 2018
    13 // Update Count     : 33
     12// Last Modified On : Thu Nov  1 21:00:56 2018
     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 ) {
    455                         convCost += computeConversionCost( assert->second.actualType, assert->second.formalType, indexer, alt.env );
     476                // specialization cost of return types can't be accounted for directly, it disables
     477                // otherwise-identical calls, like this example based on auto-newline in the I/O lib:
     478                //
     479                //   forall(otype OS) {
     480                //     void ?|?(OS&, int);  // with newline
     481                //     OS&  ?|?(OS&, int);  // no newline, always chosen due to more specialization
     482                //   }
     483
     484                // mark type variable and specialization cost of forall clause
     485                convCost.incVar( function->forall.size() );
     486                for ( TypeDecl* td : function->forall ) {
     487                        convCost.decSpec( td->assertions.size() );
    456488                }
    457489
     
    466498                                needAssertions[ *assert ].isUsed = true;
    467499                        }
    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         }
     500                }
     501        }
     502
     503        /// Unique identifier for matching expression resolutions to their requesting expression
     504        UniqueId globalResnSlot = 0;
    585505
    586506        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 //          )
     507        void AlternativeFinder::Finder::inferParameters( Alternative &newAlt, OutputIterator out ) {
     508                // Set need bindings for any unbound assertions
     509                UniqueId crntResnSlot = 0;  // matching ID for this expression's assertions
     510                for ( auto& assn : newAlt.need ) {
     511                        // skip already-matched assertions
     512                        if ( assn.info.resnSlot != 0 ) continue;
     513                        // assign slot for expression if needed
     514                        if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; }
     515                        // fix slot to assertion
     516                        assn.info.resnSlot = crntResnSlot;
     517                }
     518                // pair slot to expression
     519                if ( crntResnSlot != 0 ) { newAlt.expr->resnSlots.push_back( crntResnSlot ); }
     520
     521                // add to output list, assertion resolution is deferred
     522                *out++ = newAlt;
    613523        }
    614524
     
    951861                }
    952862                // build and validate new alternative
    953                 Alternative newAlt( appExpr, result.env, cost );
     863                Alternative newAlt{ appExpr, result.env, result.openVars, result.need, cost };
    954864                PRINT(
    955865                        std::cerr << "instantiate function success: " << appExpr << std::endl;
     
    957867                        printAssertionSet( result.need, std::cerr, 8 );
    958868                )
    959                 inferParameters( result.need, result.have, newAlt, result.openVars, out );
     869                inferParameters( newAlt, out );
    960870        }
    961871
     
    12021112
    12031113                // 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
     1114                // for implicit conversions to each of the anonymous members, must happen after findMinCost
    12051115                // since anon conversions are never the cheapest expression
    12061116                for ( const Alternative & alt : winners ) {
     
    12341144                        if ( isLvalue( alt.expr ) ) {
    12351145                                alternatives.push_back(
    1236                                         Alternative{ new AddressExpr( alt.expr->clone() ), alt.env, alt.cost } );
     1146                                        Alternative{ alt, new AddressExpr( alt.expr->clone() ), alt.cost } );
    12371147                        } // if
    12381148                } // for
     
    12401150
    12411151        void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) {
    1242                 alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } );
     1152                alternatives.push_back( Alternative{ expr->clone(), env } );
    12431153        }
    12441154
     
    12851195                AltList candidates;
    12861196                for ( Alternative & alt : finder.alternatives ) {
    1287                         AssertionSet needAssertions, haveAssertions;
    1288                         OpenVarSet openVars;
     1197                        AssertionSet needAssertions( alt.need.begin(), alt.need.end() );
     1198                        AssertionSet haveAssertions;
     1199                        OpenVarSet openVars{ alt.openVars };
    12891200
    12901201                        alt.env.extractOpenVars( openVars );
     
    13141225                                // count one safe conversion for each value that is thrown away
    13151226                                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 ) );
     1227                                Alternative newAlt{
     1228                                        restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ),
     1229                                        alt.env, openVars, needAssertions, alt.cost, alt.cost + thisCost };
     1230                                inferParameters( newAlt, back_inserter( candidates ) );
    13201231                        } // if
    13211232                } // for
     
    13301241
    13311242        void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) {
    1332                 assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." );
     1243                assertf( castExpr->get_result(), "Implicit virtual cast targets not yet supported." );
    13331244                AlternativeFinder finder( indexer, env );
    13341245                // don't prune here, since it's guaranteed all alternatives will have the same type
    13351246                finder.findWithoutPrune( castExpr->get_arg() );
    13361247                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 ) );
     1248                        alternatives.push_back( Alternative{
     1249                                alt, new VirtualCastExpr{ alt.expr->clone(), castExpr->get_result()->clone() },
     1250                                alt.cost } );
    13401251                }
    13411252        }
     
    13441255                /// Gets name from untyped member expression (member must be NameExpr)
    13451256                const std::string& get_member_name( UntypedMemberExpr *memberExpr ) {
     1257                        if ( dynamic_cast< ConstantExpr * >( memberExpr->get_member() ) ) {
     1258                                SemanticError( memberExpr, "Indexed access to struct fields unsupported: " );
     1259                        } // if
    13461260                        NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() );
    13471261                        assert( nameExpr );
     
    13621276                        // find member of the given type
    13631277                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    1364                                 addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
     1278                                addAggMembers( structInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
    13651279                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    1366                                 addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
     1280                                addAggMembers( unionInst, aggrExpr, *agg, cost, get_member_name(memberExpr) );
    13671281                        } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
    1368                                 addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );
     1282                                addTupleMembers( tupleType, aggrExpr, *agg, cost, memberExpr->get_member() );
    13691283                        } // if
    13701284                } // for
     
    13721286
    13731287        void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) {
    1374                 alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) );
     1288                alternatives.push_back( Alternative{ memberExpr->clone(), env } );
    13751289        }
    13761290
     
    13851299                        // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
    13861300                        // can't construct in place and use vector::back
    1387                         Alternative newAlt( newExpr, env, Cost::zero, cost );
     1301                        Alternative newAlt{ newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost };
    13881302                        PRINT(
    13891303                                std::cerr << "decl is ";
     
    14031317                // not sufficient to clone here, because variable's type may have changed
    14041318                // since the VariableExpr was originally created.
    1405                 alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) );
     1319                alternatives.push_back( Alternative{ new VariableExpr{ variableExpr->var }, env } );
    14061320        }
    14071321
    14081322        void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) {
    1409                 alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) );
     1323                alternatives.push_back( Alternative{ constantExpr->clone(), env } );
    14101324        }
    14111325
     
    14131327                if ( sizeofExpr->get_isType() ) {
    14141328                        Type * newType = sizeofExpr->get_type()->clone();
    1415                         alternatives.push_back( Alternative( new SizeofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
     1329                        alternatives.push_back( Alternative{
     1330                                new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } );
    14161331                } else {
    14171332                        // find all alternatives for the argument to sizeof
     
    14271342                        Alternative &choice = winners.front();
    14281343                        referenceToRvalueConversion( choice.expr, choice.cost );
    1429                         alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
     1344                        alternatives.push_back( Alternative{
     1345                                choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } );
    14301346                } // if
    14311347        }
     
    14341350                if ( alignofExpr->get_isType() ) {
    14351351                        Type * newType = alignofExpr->get_type()->clone();
    1436                         alternatives.push_back( Alternative( new AlignofExpr( resolveTypeof( newType, indexer ) ), env, Cost::zero ) );
     1352                        alternatives.push_back( Alternative{
     1353                                new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } );
    14371354                } else {
    14381355                        // find all alternatives for the argument to sizeof
     
    14481365                        Alternative &choice = winners.front();
    14491366                        referenceToRvalueConversion( choice.expr, choice.cost );
    1450                         alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
     1367                        alternatives.push_back( Alternative{
     1368                                choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } );
    14511369                } // if
    14521370        }
     
    14581376                for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    14591377                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
    1460                                 alternatives.push_back( Alternative( new OffsetofExpr( aggInst->clone(), dwt ), env, Cost::zero ) );
     1378                                alternatives.push_back( Alternative{
     1379                                        new OffsetofExpr{ aggInst->clone(), dwt }, env } );
    14611380                                renameTypes( alternatives.back().expr );
    14621381                        } else {
     
    14771396
    14781397        void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) {
    1479                 alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) );
     1398                alternatives.push_back( Alternative{ offsetofExpr->clone(), env } );
    14801399        }
    14811400
    14821401        void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) {
    1483                 alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) );
     1402                alternatives.push_back( Alternative{ offsetPackExpr->clone(), env } );
    14841403        }
    14851404
     
    15011420                                Cost cost = Cost::zero;
    15021421                                Expression * newExpr = data.combine( cost );
    1503                                 alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) );
     1422                                alternatives.push_back( Alternative{
     1423                                        new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{},
     1424                                        AssertionList{}, Cost::zero, cost } );
    15041425                                for ( DeclarationWithType * retVal : function->returnVals ) {
    15051426                                        alternatives.back().expr->result = retVal->get_type()->clone();
     
    15401461                                Cost cost = Cost::zero;
    15411462                                Expression * newExpr = data.combine( cost );
    1542                                 alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) );
     1463                                alternatives.push_back( Alternative{
     1464                                        newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost } );
    15431465                                renameTypes( alternatives.back().expr );
    15441466                        } // for
     
    15551477                for ( const Alternative & first : firstFinder.alternatives ) {
    15561478                        for ( const Alternative & second : secondFinder.alternatives ) {
    1557                                 TypeEnvironment compositeEnv;
    1558                                 compositeEnv.simpleCombine( first.env );
     1479                                TypeEnvironment compositeEnv{ first.env };
    15591480                                compositeEnv.simpleCombine( second.env );
    1560 
    1561                                 LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() );
    1562                                 alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) );
     1481                                OpenVarSet openVars{ first.openVars };
     1482                                mergeOpenVars( openVars, second.openVars );
     1483                                AssertionSet need;
     1484                                cloneAll( first.need, need );
     1485                                cloneAll( second.need, need );
     1486
     1487                                LogicalExpr *newExpr = new LogicalExpr{
     1488                                        first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() };
     1489                                alternatives.push_back( Alternative{
     1490                                        newExpr, std::move(compositeEnv), std::move(openVars),
     1491                                        AssertionList( need.begin(), need.end() ), first.cost + second.cost } );
    15631492                        }
    15641493                }
     
    15811510                        for ( const Alternative & second : secondFinder.alternatives ) {
    15821511                                for ( const Alternative & third : thirdFinder.alternatives ) {
    1583                                         TypeEnvironment compositeEnv;
    1584                                         compositeEnv.simpleCombine( first.env );
     1512                                        TypeEnvironment compositeEnv{ first.env };
    15851513                                        compositeEnv.simpleCombine( second.env );
    15861514                                        compositeEnv.simpleCombine( third.env );
    1587 
     1515                                        OpenVarSet openVars{ first.openVars };
     1516                                        mergeOpenVars( openVars, second.openVars );
     1517                                        mergeOpenVars( openVars, third.openVars );
     1518                                        AssertionSet need;
     1519                                        cloneAll( first.need, need );
     1520                                        cloneAll( second.need, need );
     1521                                        cloneAll( third.need, need );
     1522                                        AssertionSet have;
     1523                                       
    15881524                                        // unify true and false types, then infer parameters to produce new alternatives
    1589                                         OpenVarSet openVars;
    1590                                         AssertionSet needAssertions, haveAssertions;
    1591                                         Alternative newAlt( 0, compositeEnv, first.cost + second.cost + third.cost );
    15921525                                        Type* commonType = nullptr;
    1593                                         if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    1594                                                 ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() );
     1526                                        if ( unify( second.expr->result, third.expr->result, compositeEnv,
     1527                                                        need, have, openVars, indexer, commonType ) ) {
     1528                                                ConditionalExpr *newExpr = new ConditionalExpr{
     1529                                                        first.expr->clone(), second.expr->clone(), third.expr->clone() };
    15951530                                                newExpr->result = commonType ? commonType : second.expr->result->clone();
    15961531                                                // convert both options to the conditional result type
    1597                                                 newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env );
    1598                                                 newAlt.cost += computeExpressionConversionCost( newExpr->arg3, newExpr->result, indexer, newAlt.env );
    1599                                                 newAlt.expr = newExpr;
    1600                                                 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
     1532                                                Cost cost = first.cost + second.cost + third.cost;
     1533                                                cost += computeExpressionConversionCost(
     1534                                                        newExpr->arg2, newExpr->result, indexer, compositeEnv );
     1535                                                cost += computeExpressionConversionCost(
     1536                                                        newExpr->arg3, newExpr->result, indexer, compositeEnv );
     1537                                                // output alternative
     1538                                                Alternative newAlt{
     1539                                                        newExpr, std::move(compositeEnv), std::move(openVars),
     1540                                                        AssertionList( need.begin(), need.end() ), cost };
     1541                                                inferParameters( newAlt, back_inserter( alternatives ) );
    16011542                                        } // if
    16021543                                } // for
     
    16111552                secondFinder.findWithAdjustment( commaExpr->get_arg2() );
    16121553                for ( const Alternative & alt : secondFinder.alternatives ) {
    1613                         alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) );
     1554                        alternatives.push_back( Alternative{
     1555                                alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } );
    16141556                } // for
    16151557                delete newFirstArg;
     
    16261568                for ( const Alternative & first : firstFinder.alternatives ) {
    16271569                        for ( const Alternative & second : secondFinder.alternatives ) {
    1628                                 TypeEnvironment compositeEnv;
    1629                                 compositeEnv.simpleCombine( first.env );
     1570                                TypeEnvironment compositeEnv{ first.env };
    16301571                                compositeEnv.simpleCombine( second.env );
    1631                                 OpenVarSet openVars;
    1632                                 AssertionSet needAssertions, haveAssertions;
    1633                                 Alternative newAlt( 0, compositeEnv, first.cost + second.cost );
     1572                                OpenVarSet openVars{ first.openVars };
     1573                                mergeOpenVars( openVars, second.openVars );
     1574                                AssertionSet need;
     1575                                cloneAll( first.need, need );
     1576                                cloneAll( second.need, need );
     1577                                AssertionSet have;
     1578
    16341579                                Type* commonType = nullptr;
    1635                                 if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    1636                                         RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() );
     1580                                if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have,
     1581                                                openVars, indexer, commonType ) ) {
     1582                                        RangeExpr * newExpr =
     1583                                                new RangeExpr{ first.expr->clone(), second.expr->clone() };
    16371584                                        newExpr->result = commonType ? commonType : first.expr->result->clone();
    1638                                         newAlt.expr = newExpr;
    1639                                         inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
     1585                                        Alternative newAlt{
     1586                                                newExpr, std::move(compositeEnv), std::move(openVars),
     1587                                                AssertionList( need.begin(), need.end() ), first.cost + second.cost };
     1588                                        inferParameters( newAlt, back_inserter( alternatives ) );
    16401589                                } // if
    16411590                        } // for
     
    16551604
    16561605                        TypeEnvironment compositeEnv;
    1657                         simpleCombineEnvironments( alts.begin(), alts.end(), compositeEnv );
    1658                         alternatives.push_back(
    1659                                 Alternative{ new TupleExpr( exprs ), compositeEnv, sumCost( alts ) } );
     1606                        OpenVarSet openVars;
     1607                        AssertionSet need;
     1608                        for ( const Alternative& alt : alts ) {
     1609                                compositeEnv.simpleCombine( alt.env );
     1610                                mergeOpenVars( openVars, alt.openVars );
     1611                                cloneAll( alt.need, need );
     1612                        }
     1613                       
     1614                        alternatives.push_back( Alternative{
     1615                                new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars),
     1616                                AssertionList( need.begin(), need.end() ), sumCost( alts ) } );
    16601617                } // for
    16611618        }
    16621619
    16631620        void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) {
    1664                 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
     1621                alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
    16651622        }
    16661623
    16671624        void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    1668                 alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );
     1625                alternatives.push_back( Alternative{ impCpCtorExpr->clone(), env } );
    16691626        }
    16701627
     
    16751632                finder.findWithoutPrune( ctorExpr->get_callExpr() );
    16761633                for ( Alternative & alt : finder.alternatives ) {
    1677                         alternatives.push_back( Alternative( new ConstructorExpr( alt.expr->clone() ), alt.env, alt.cost ) );
     1634                        alternatives.push_back( Alternative{
     1635                                alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } );
    16781636                }
    16791637        }
    16801638
    16811639        void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) {
    1682                 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
     1640                alternatives.push_back( Alternative{ tupleExpr->clone(), env } );
    16831641        }
    16841642
    16851643        void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) {
    1686                 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) );
     1644                alternatives.push_back( Alternative{ tupleAssignExpr->clone(), env } );
    16871645        }
    16881646
     
    16931651                        // ensure that the id is passed on to the UniqueExpr alternative so that the expressions are "linked"
    16941652                        UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() );
    1695                         alternatives.push_back( Alternative( newUnqExpr, alt.env, alt.cost ) );
     1653                        alternatives.push_back( Alternative{ alt, newUnqExpr, alt.cost } );
    16961654                }
    16971655        }
     
    17011659                ResolvExpr::resolveStmtExpr( newStmtExpr, indexer );
    17021660                // xxx - this env is almost certainly wrong, and needs to somehow contain the combined environments from all of the statements in the stmtExpr...
    1703                 alternatives.push_back( Alternative( newStmtExpr, env, Cost::zero ) );
     1661                alternatives.push_back( Alternative{ newStmtExpr, env } );
    17041662        }
    17051663
     
    17231681                        for ( Alternative & alt : finder.get_alternatives() ) {
    17241682                                TypeEnvironment newEnv( alt.env );
    1725                                 AssertionSet needAssertions, haveAssertions;
    1726                                 OpenVarSet openVars;  // find things in env that don't have a "representative type" and claim those are open vars?
     1683                                AssertionSet need;
     1684                                cloneAll( alt.need, need );
     1685                                AssertionSet have;
     1686                                OpenVarSet openVars( alt.openVars ); 
     1687                                // xxx - find things in env that don't have a "representative type" and claim
     1688                                // those are open vars?
    17271689                                PRINT(
    17281690                                        std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
    17291691                                )
    1730                                 // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
    1731                                 // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
    1732                                 // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    1733                                 // to.
     1692                                // It's possible that a cast can throw away some values in a multiply-valued
     1693                                // expression. (An example is a cast-to-void, which casts from one value to
     1694                                // zero.)  Figure out the prefix of the subexpression results that are cast
     1695                                // directly.  The candidate is invalid if it has fewer results than there are
     1696                                // types to cast to.
    17341697                                int discardedValues = alt.expr->result->size() - toType->size();
    17351698                                if ( discardedValues < 0 ) continue;
    1736                                 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    1737                                 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
     1699                                // xxx - may need to go into tuple types and extract relevant types and use
     1700                                // unifyList. Note that currently, this does not allow casting a tuple to an
     1701                                // atomic type (e.g. (int)([1, 2, 3]))
     1702                               
    17381703                                // unification run for side-effects
    1739                                 unify( toType, alt.expr->result, newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type??
     1704                                unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer );
     1705                                // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?
    17401706
    17411707                                Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv );
     
    17431709                                        // count one safe conversion for each value that is thrown away
    17441710                                        thisCost.incSafe( discardedValues );
    1745                                         Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost );
    1746                                         inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
     1711                                        Alternative newAlt{
     1712                                                new InitExpr{
     1713                                                        restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() },
     1714                                                std::move(newEnv), std::move(openVars),
     1715                                                AssertionList( need.begin(), need.end() ), alt.cost, thisCost };
     1716                                        inferParameters( newAlt, back_inserter( candidates ) );
    17471717                                }
    17481718                        }
Note: See TracChangeset for help on using the changeset viewer.