Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CandidateFinder.cpp

    r18e683b rcf32116  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed Jun 5 14:30:00 2019
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Wed Jun 5 14:30:00 2019
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Oct  1 14:55:00 2019
     13// Update Count     : 2
    1414//
    1515
     
    5454                return new ast::CastExpr{ expr, expr->result->stripReferences() };
    5555        }
    56        
     56
    5757        return expr;
    5858}
     
    6161UniqueId globalResnSlot = 0;
    6262
    63 Cost computeConversionCost( 
    64         const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab,
    65         const ast::TypeEnvironment & env
     63Cost computeConversionCost(
     64        const ast::Type * argType, const ast::Type * paramType, bool argIsLvalue,
     65        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
    6666) {
    6767        PRINT(
     
    7474                std::cerr << std::endl;
    7575        )
    76         Cost convCost = conversionCost( argType, paramType, symtab, env );
     76        Cost convCost = conversionCost( argType, paramType, argIsLvalue, symtab, env );
    7777        PRINT(
    7878                std::cerr << std::endl << "cost is " << convCost << std::endl;
     
    107107
    108108        /// Computes conversion cost for a given expression to a given type
    109         const ast::Expr * computeExpressionConversionCost( 
    110                 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 
     109        const ast::Expr * computeExpressionConversionCost(
     110                const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost
    111111        ) {
    112                 Cost convCost = computeConversionCost( arg->result, paramType, symtab, env );
     112                Cost convCost = computeConversionCost(
     113                                arg->result, paramType, arg->get_lvalue(), symtab, env );
    113114                outCost += convCost;
    114115
    115                 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires 
    116                 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 
     116                // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires
     117                // conversion. Ignore poly cost for now, since this requires resolution of the cast to
    117118                // infer parameters and this does not currently work for the reason stated below
    118119                Cost tmpCost = convCost;
     
    123124                        return new ast::CastExpr{ arg, newType };
    124125
    125                         // xxx - *should* be able to resolve this cast, but at the moment pointers are not 
    126                         // castable to zero_t, but are implicitly convertible. This is clearly inconsistent, 
     126                        // xxx - *should* be able to resolve this cast, but at the moment pointers are not
     127                        // castable to zero_t, but are implicitly convertible. This is clearly inconsistent,
    127128                        // once this is fixed it should be possible to resolve the cast.
    128                         // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable, 
    129                         // but it shouldn't be because this makes the conversion from DT* to DT* since 
     129                        // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable,
     130                        // but it shouldn't be because this makes the conversion from DT* to DT* since
    130131                        // commontype(zero_t, DT*) is DT*, rather than nothing
    131132
    132133                        // CandidateFinder finder{ symtab, env };
    133134                        // finder.find( arg, ResolvMode::withAdjustment() );
    134                         // assertf( finder.candidates.size() > 0, 
     135                        // assertf( finder.candidates.size() > 0,
    135136                        //      "Somehow castable expression failed to find alternatives." );
    136                         // assertf( finder.candidates.size() == 1, 
     137                        // assertf( finder.candidates.size() == 1,
    137138                        //      "Somehow got multiple alternatives for known cast expression." );
    138139                        // return finder.candidates.front()->expr;
     
    143144
    144145        /// Computes conversion cost for a given candidate
    145         Cost computeApplicationConversionCost( 
    146                 CandidateRef cand, const ast::SymbolTable & symtab 
     146        Cost computeApplicationConversionCost(
     147                CandidateRef cand, const ast::SymbolTable & symtab
    147148        ) {
    148149                auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >();
     
    167168                                if ( function->isVarArgs ) {
    168169                                        convCost.incUnsafe();
    169                                         PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 
     170                                        PRINT( std::cerr << "end of params with varargs function: inc unsafe: "
    170171                                                << convCost << std::endl; ; )
    171172                                        // convert reference-typed expressions into value-typed expressions
    172                                         cand->expr = ast::mutate_field_index( 
    173                                                 appExpr, &ast::ApplicationExpr::args, i, 
     173                                        cand->expr = ast::mutate_field_index(
     174                                                appExpr, &ast::ApplicationExpr::args, i,
    174175                                                referenceToRvalueConversion( args[i], convCost ) );
    175176                                        continue;
     
    180181                                // Default arguments should be free - don't include conversion cost.
    181182                                // Unwrap them here because they are not relevant to the rest of the system
    182                                 cand->expr = ast::mutate_field_index( 
     183                                cand->expr = ast::mutate_field_index(
    183184                                        appExpr, &ast::ApplicationExpr::args, i, def->expr );
    184185                                ++param;
     
    188189                        // mark conversion cost and also specialization cost of param type
    189190                        const ast::Type * paramType = (*param)->get_type();
    190                         cand->expr = ast::mutate_field_index( 
    191                                 appExpr, &ast::ApplicationExpr::args, i, 
    192                                 computeExpressionConversionCost( 
     191                        cand->expr = ast::mutate_field_index(
     192                                appExpr, &ast::ApplicationExpr::args, i,
     193                                computeExpressionConversionCost(
    193194                                        args[i], paramType, symtab, cand->env, convCost ) );
    194195                        convCost.decSpec( specCost( paramType ) );
     
    198199                if ( param != params.end() ) return Cost::infinity;
    199200
    200                 // specialization cost of return types can't be accounted for directly, it disables 
     201                // specialization cost of return types can't be accounted for directly, it disables
    201202                // otherwise-identical calls, like this example based on auto-newline in the I/O lib:
    202203                //
     
    215216        }
    216217
    217         void makeUnifiableVars( 
    218                 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars, 
    219                 ast::AssertionSet & need 
     218        void makeUnifiableVars(
     219                const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars,
     220                ast::AssertionSet & need
    220221        ) {
    221222                for ( const ast::TypeDecl * tyvar : type->forall ) {
     
    254255
    255256                ArgPack()
    256                 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 
     257                : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ),
    257258                  tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    258                
    259                 ArgPack( 
    260                         const ast::TypeEnvironment & env, const ast::AssertionSet & need, 
     259
     260                ArgPack(
     261                        const ast::TypeEnvironment & env, const ast::AssertionSet & need,
    261262                        const ast::AssertionSet & have, const ast::OpenVarSet & open )
    262                 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 
     263                : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ),
    263264                  open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    264                
     265
    265266                ArgPack(
    266                         std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env, 
    267                         ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open, 
    268                         unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero, 
     267                        std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env,
     268                        ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open,
     269                        unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero,
    269270                        unsigned nextExpl = 0, unsigned explAlt = 0 )
    270271                : parent(parent), expr( expr ), cost( cost ), env( move( env ) ), need( move( need ) ),
    271272                  have( move( have ) ), open( move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ),
    272273                  nextExpl( nextExpl ), explAlt( explAlt ) {}
    273                
     274
    274275                ArgPack(
    275                         const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 
     276                        const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need,
    276277                        ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added )
    277                 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ), 
    278                   need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ), 
     278                : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ),
     279                  need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ),
    279280                  tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {}
    280                
     281
    281282                /// true if this pack is in the middle of an exploded argument
    282283                bool hasExpl() const { return nextExpl > 0; }
     
    286287                        return args[ nextArg-1 ][ explAlt ];
    287288                }
    288                
     289
    289290                /// Ends a tuple expression, consolidating the appropriate args
    290291                void endTuple( const std::vector< ArgPack > & packs ) {
     
    307308
    308309        /// Instantiates an argument to match a parameter, returns false if no matching results left
    309         bool instantiateArgument( 
    310                 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args, 
    311                 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 
    312                 unsigned nTuples = 0 
     310        bool instantiateArgument(
     311                const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args,
     312                std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,
     313                unsigned nTuples = 0
    313314        ) {
    314315                if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) {
     
    318319                                // xxx - dropping initializer changes behaviour from previous, but seems correct
    319320                                // ^^^ need to handle the case where a tuple has a default argument
    320                                 if ( ! instantiateArgument( 
     321                                if ( ! instantiateArgument(
    321322                                        type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;
    322323                                nTuples = 0;
     
    329330                } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) {
    330331                        // paramType is a ttype, consumes all remaining arguments
    331                        
     332
    332333                        // completed tuples; will be spliced to end of results to finish
    333334                        std::vector< ArgPack > finalResults{};
     
    342343                                for ( std::size_t i = genStart; i < genEnd; ++i ) {
    343344                                        unsigned nextArg = results[i].nextArg;
    344                                        
     345
    345346                                        // use next element of exploded tuple if present
    346347                                        if ( results[i].hasExpl() ) {
     
    352353                                                results.emplace_back(
    353354                                                        i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),
    354                                                         copy( results[i].need ), copy( results[i].have ), 
     355                                                        copy( results[i].need ), copy( results[i].have ),
    355356                                                        copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl,
    356357                                                        results[i].explAlt );
     
    370371                                                        // push empty tuple expression
    371372                                                        newResult.parent = i;
    372                                                         std::vector< ast::ptr< ast::Expr > > emptyList;
    373                                                         newResult.expr =
    374                                                                 new ast::TupleExpr{ CodeLocation{}, move( emptyList ) };
     373                                                        newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} };
    375374                                                        argType = newResult.expr->result;
    376375                                                } else {
     
    400399
    401400                                                // check unification for ttype before adding to final
    402                                                 if ( 
    403                                                         unify( 
     401                                                if (
     402                                                        unify(
    404403                                                                ttype, argType, newResult.env, newResult.need, newResult.have,
    405                                                                 newResult.open, symtab ) 
     404                                                                newResult.open, symtab )
    406405                                                ) {
    407406                                                        finalResults.emplace_back( move( newResult ) );
     
    424423                                                if ( expl.exprs.empty() ) {
    425424                                                        results.emplace_back(
    426                                                                 results[i], move( env ), copy( results[i].need ), 
     425                                                                results[i], move( env ), copy( results[i].need ),
    427426                                                                copy( results[i].have ), move( open ), nextArg + 1, expl.cost );
    428                                                        
     427
    429428                                                        continue;
    430429                                                }
     
    432431                                                // add new result
    433432                                                results.emplace_back(
    434                                                         i, expl.exprs.front(), move( env ), copy( results[i].need ), 
    435                                                         copy( results[i].have ), move( open ), nextArg + 1, nTuples, 
     433                                                        i, expl.exprs.front(), move( env ), copy( results[i].need ),
     434                                                        copy( results[i].have ), move( open ), nextArg + 1, nTuples,
    436435                                                        expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    437436                                        }
     
    479478
    480479                                        results.emplace_back(
    481                                                 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 
     480                                                i, expr, move( env ), move( need ), move( have ), move( open ), nextArg,
    482481                                                nTuples, Cost::zero, nextExpl, results[i].explAlt );
    483482                                }
     
    495494                                        if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {
    496495                                                results.emplace_back(
    497                                                         i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 
     496                                                        i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ),
    498497                                                        move( need ), move( have ), move( open ), nextArg, nTuples );
    499498                                        }
     
    517516                                if ( expl.exprs.empty() ) {
    518517                                        results.emplace_back(
    519                                                 results[i], move( env ), move( need ), move( have ), move( open ), 
     518                                                results[i], move( env ), move( need ), move( have ), move( open ),
    520519                                                nextArg + 1, expl.cost );
    521                                        
     520
    522521                                        continue;
    523522                                }
     
    539538                                        // add new result
    540539                                        results.emplace_back(
    541                                                 i, expr, move( env ), move( need ), move( have ), move( open ), 
     540                                                i, expr, move( env ), move( need ), move( have ), move( open ),
    542541                                                nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    543542                                }
     
    548547                genStart = genEnd;
    549548
    550                 return genEnd != results.size();
     549                return genEnd != results.size();  // were any new results added?
    551550        }
    552551
    553552        /// Generate a cast expression from `arg` to `toType`
    554         const ast::Expr * restructureCast( 
     553        const ast::Expr * restructureCast(
    555554                ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast
    556555        ) {
    557                 if ( 
    558                         arg->result->size() > 1 
    559                         && ! toType->isVoid() 
    560                         && ! dynamic_cast< const ast::ReferenceType * >( toType ) 
     556                if (
     557                        arg->result->size() > 1
     558                        && ! toType->isVoid()
     559                        && ! dynamic_cast< const ast::ReferenceType * >( toType )
    561560                ) {
    562                         // Argument is a tuple and the target type is neither void nor a reference. Cast each 
    563                         // member of the tuple to its corresponding target type, producing the tuple of those 
    564                         // cast expressions. If there are more components of the tuple than components in the 
    565                         // target type, then excess components do not come out in the result expression (but 
     561                        // Argument is a tuple and the target type is neither void nor a reference. Cast each
     562                        // member of the tuple to its corresponding target type, producing the tuple of those
     563                        // cast expressions. If there are more components of the tuple than components in the
     564                        // target type, then excess components do not come out in the result expression (but
    566565                        // UniqueExpr ensures that the side effects will still be produced)
    567566                        if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {
    568                                 // expressions which may contain side effects require a single unique instance of 
     567                                // expressions which may contain side effects require a single unique instance of
    569568                                // the expression
    570569                                arg = new ast::UniqueExpr{ arg->location, arg };
     
    574573                                // cast each component
    575574                                ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i };
    576                                 components.emplace_back( 
     575                                components.emplace_back(
    577576                                        restructureCast( idx, toType->getComponent( i ), isGenerated ) );
    578577                        }
     
    594593
    595594        /// Actually visits expressions to find their candidate interpretations
    596         struct Finder final : public ast::WithShortCircuiting {
     595        class Finder final : public ast::WithShortCircuiting {
     596                const ast::SymbolTable & symtab;
     597        public:
    597598                CandidateFinder & selfFinder;
    598                 const ast::SymbolTable & symtab;
    599599                CandidateList & candidates;
    600600                const ast::TypeEnvironment & tenv;
     
    602602
    603603                Finder( CandidateFinder & f )
    604                 : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
     604                : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
    605605                  targetType( f.targetType ) {}
    606                
     606
    607607                void previsit( const ast::Node * ) { visit_children = false; }
    608608
     
    639639
    640640                /// Completes a function candidate with arguments located
    641                 void validateFunctionCandidate( 
    642                         const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 
    643                         CandidateList & out 
     641                void validateFunctionCandidate(
     642                        const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,
     643                        CandidateList & out
    644644                ) {
    645                         ast::ApplicationExpr * appExpr = 
     645                        ast::ApplicationExpr * appExpr =
    646646                                new ast::ApplicationExpr{ func->expr->location, func->expr };
    647647                        // sum cost and accumulate arguments
     
    657657                        appExpr->args = move( vargs );
    658658                        // build and validate new candidate
    659                         auto newCand = 
     659                        auto newCand =
    660660                                std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );
    661661                        PRINT(
     
    669669                /// Builds a list of candidates for a function, storing them in out
    670670                void makeFunctionCandidates(
    671                         const CandidateRef & func, const ast::FunctionType * funcType, 
     671                        const CandidateRef & func, const ast::FunctionType * funcType,
    672672                        const ExplodedArgs_new & args, CandidateList & out
    673673                ) {
     
    676676                        ast::TypeEnvironment funcEnv{ func->env };
    677677                        makeUnifiableVars( funcType, funcOpen, funcNeed );
    678                         // add all type variables as open variables now so that those not used in the parameter
    679                         // list are still considered open
     678                        // add all type variables as open variables now so that those not used in the
     679                        // parameter list are still considered open
    680680                        funcEnv.add( funcType->forall );
    681681
     
    683683                                // attempt to narrow based on expected target type
    684684                                const ast::Type * returnType = funcType->returns.front()->get_type();
    685                                 if ( ! unify( 
    686                                         returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 
     685                                if ( ! unify(
     686                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
    687687                                ) {
    688688                                        // unification failed, do not pursue this candidate
     
    698698                        for ( const ast::DeclWithType * param : funcType->params ) {
    699699                                auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
    700                                 // Try adding the arguments corresponding to the current parameter to the existing 
     700                                // Try adding the arguments corresponding to the current parameter to the existing
    701701                                // matches
    702                                 if ( ! instantiateArgument( 
     702                                if ( ! instantiateArgument(
    703703                                        obj->type, obj->init, args, results, genStart, symtab ) ) return;
    704704                        }
     
    750750                                                        if ( expl.exprs.empty() ) {
    751751                                                                results.emplace_back(
    752                                                                         results[i], move( env ), copy( results[i].need ), 
    753                                                                         copy( results[i].have ), move( open ), nextArg + 1, 
     752                                                                        results[i], move( env ), copy( results[i].need ),
     753                                                                        copy( results[i].have ), move( open ), nextArg + 1,
    754754                                                                        expl.cost );
    755755
     
    760760                                                        results.emplace_back(
    761761                                                                i, expl.exprs.front(), move( env ), copy( results[i].need ),
    762                                                                 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 
     762                                                                copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost,
    763763                                                                expl.exprs.size() == 1 ? 0 : 1, j );
    764764                                                }
     
    780780                /// Adds implicit struct-conversions to the alternative list
    781781                void addAnonConversions( const CandidateRef & cand ) {
    782                         // adds anonymous member interpretations whenever an aggregate value type is seen. 
    783                         // it's okay for the aggregate expression to have reference type -- cast it to the 
     782                        // adds anonymous member interpretations whenever an aggregate value type is seen.
     783                        // it's okay for the aggregate expression to have reference type -- cast it to the
    784784                        // base type to treat the aggregate as the referenced value
    785785                        ast::ptr< ast::Expr > aggrExpr( cand->expr );
    786786                        ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;
    787787                        cand->env.apply( aggrType );
    788                        
     788
    789789                        if ( aggrType.as< ast::ReferenceType >() ) {
    790790                                aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };
     
    799799
    800800                /// Adds aggregate member interpretations
    801                 void addAggMembers( 
    802                         const ast::ReferenceToType * aggrInst, const ast::Expr * expr, 
    803                         const Candidate & cand, const Cost & addedCost, const std::string & name 
     801                void addAggMembers(
     802                        const ast::ReferenceToType * aggrInst, const ast::Expr * expr,
     803                        const Candidate & cand, const Cost & addedCost, const std::string & name
    804804                ) {
    805805                        for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {
    806806                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );
    807                                 CandidateRef newCand = std::make_shared<Candidate>( 
     807                                CandidateRef newCand = std::make_shared<Candidate>(
    808808                                        cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
    809                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     809                                // add anonymous member interpretations whenever an aggregate value type is seen
    810810                                // as a member expression
    811811                                addAnonConversions( newCand );
     
    815815
    816816                /// Adds tuple member interpretations
    817                 void addTupleMembers( 
    818                         const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 
    819                         const Cost & addedCost, const ast::Expr * member 
     817                void addTupleMembers(
     818                        const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,
     819                        const Cost & addedCost, const ast::Expr * member
    820820                ) {
    821821                        if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) {
    822                                 // get the value of the constant expression as an int, must be between 0 and the 
     822                                // get the value of the constant expression as an int, must be between 0 and the
    823823                                // length of the tuple to have meaning
    824824                                long long val = constantExpr->intValue();
    825825                                if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    826826                                        addCandidate(
    827                                                 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 
     827                                                cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },
    828828                                                addedCost );
    829829                                }
     
    837837                        if ( funcFinder.candidates.empty() ) return;
    838838
    839                         std::vector< CandidateFinder > argCandidates = 
     839                        std::vector< CandidateFinder > argCandidates =
    840840                                selfFinder.findSubExprs( untypedExpr->args );
    841                        
     841
    842842                        // take care of possible tuple assignments
    843843                        // if not tuple assignment, handled as normal function call
     
    877877                                                if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    878878                                                        CandidateRef newFunc{ new Candidate{ *func } };
    879                                                         newFunc->expr = 
     879                                                        newFunc->expr =
    880880                                                                referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    881881                                                        makeFunctionCandidates( newFunc, function, argExpansions, found );
    882882                                                }
    883                                         } else if ( 
    884                                                 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 
     883                                        } else if (
     884                                                auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
    885885                                        ) {
    886886                                                if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) {
    887887                                                        if ( auto function = clz->bound.as< ast::FunctionType >() ) {
    888888                                                                CandidateRef newFunc{ new Candidate{ *func } };
    889                                                                 newFunc->expr = 
     889                                                                newFunc->expr =
    890890                                                                        referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    891891                                                                makeFunctionCandidates( newFunc, function, argExpansions, found );
     
    901901                                std::vector< ExplodedArg > funcE;
    902902                                funcE.reserve( funcFinder.candidates.size() );
    903                                 for ( const CandidateRef & func : funcFinder ) { 
     903                                for ( const CandidateRef & func : funcFinder ) {
    904904                                        funcE.emplace_back( *func, symtab );
    905905                                }
     
    913913                                                        if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    914914                                                                CandidateRef newOp{ new Candidate{ *op} };
    915                                                                 newOp->expr = 
     915                                                                newOp->expr =
    916916                                                                        referenceToRvalueConversion( newOp->expr, newOp->cost );
    917917                                                                makeFunctionCandidates( newOp, function, argExpansions, found );
     
    922922                        }
    923923
    924                         // Implement SFINAE; resolution errors are only errors if there aren't any non-error 
     924                        // Implement SFINAE; resolution errors are only errors if there aren't any non-error
    925925                        // candidates
    926926                        if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
     
    934934                                        auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
    935935                                        auto function = pointer->base.strict_as< ast::FunctionType >();
    936                                        
     936
    937937                                        std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;
    938938                                        std::cerr << "parameters are:" << std::endl;
     
    957957                        promoteCvtCost( winners );
    958958
    959                         // function may return a struct/union value, in which case we need to add candidates 
    960                         // for implicit conversions to each of the anonymous members, which must happen after 
     959                        // function may return a struct/union value, in which case we need to add candidates
     960                        // for implicit conversions to each of the anonymous members, which must happen after
    961961                        // `findMinCost`, since anon conversions are never the cheapest
    962962                        for ( const CandidateRef & c : winners ) {
     
    966966
    967967                        if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
    968                                 // If resolution is unsuccessful with a target type, try again without, since it 
     968                                // If resolution is unsuccessful with a target type, try again without, since it
    969969                                // will sometimes succeed when it wouldn't with a target type binding.
    970970                                // For example:
     
    983983                /// true if expression is an lvalue
    984984                static bool isLvalue( const ast::Expr * x ) {
    985                         return x->result && ( x->result->is_lvalue() || x->result.as< ast::ReferenceType >() );
     985                        return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() );
    986986                }
    987987
     
    10161016                                cand->env.extractOpenVars( open );
    10171017
    1018                                 // It is possible that a cast can throw away some values in a multiply-valued 
    1019                                 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the 
    1020                                 // subexpression results that are cast directly. The candidate is invalid if it 
     1018                                // It is possible that a cast can throw away some values in a multiply-valued
     1019                                // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the
     1020                                // subexpression results that are cast directly. The candidate is invalid if it
    10211021                                // has fewer results than there are types to cast to.
    10221022                                int discardedValues = cand->expr->result->size() - toType->size();
     
    10251025                                // unification run for side-effects
    10261026                                unify( toType, cand->expr->result, cand->env, need, have, open, symtab );
    1027                                 Cost thisCost = castCost( cand->expr->result, toType, symtab, cand->env );
     1027                                Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1028                                                symtab, cand->env );
    10281029                                PRINT(
    10291030                                        std::cerr << "working on cast with result: " << toType << std::endl;
     
    10371038                                        // count one safe conversion for each value that is thrown away
    10381039                                        thisCost.incSafe( discardedValues );
    1039                                         CandidateRef newCand = std::make_shared<Candidate>( 
    1040                                                 restructureCast( cand->expr, toType, castExpr->isGenerated ), 
    1041                                                 copy( cand->env ), move( open ), move( need ), cand->cost, 
     1040                                        CandidateRef newCand = std::make_shared<Candidate>(
     1041                                                restructureCast( cand->expr, toType, castExpr->isGenerated ),
     1042                                                copy( cand->env ), move( open ), move( need ), cand->cost,
    10421043                                                cand->cost + thisCost );
    10431044                                        inferParameters( newCand, matches );
     
    10571058                        finder.find( castExpr->arg, ResolvMode::withoutPrune() );
    10581059                        for ( CandidateRef & r : finder.candidates ) {
    1059                                 addCandidate( 
    1060                                         *r, 
     1060                                addCandidate(
     1061                                        *r,
    10611062                                        new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
    10621063                        }
     
    10671068                        aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    10681069                        for ( CandidateRef & agg : aggFinder.candidates ) {
    1069                                 // it's okay for the aggregate expression to have reference type -- cast it to the 
     1070                                // it's okay for the aggregate expression to have reference type -- cast it to the
    10701071                                // base type to treat the aggregate as the referenced value
    10711072                                Cost addedCost = Cost::zero;
     
    10741075                                // find member of the given type
    10751076                                if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {
    1076                                         addAggMembers( 
     1077                                        addAggMembers(
    10771078                                                structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10781079                                } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {
    1079                                         addAggMembers( 
     1080                                        addAggMembers(
    10801081                                                unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10811082                                } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {
     
    10971098
    10981099                                CandidateRef newCand = std::make_shared<Candidate>(
    1099                                         newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 
     1100                                        newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
    11001101                                        cost );
    11011102                                PRINT(
     
    11071108                                        std::cerr << std::endl;
    11081109                                )
    1109                                 newCand->expr = ast::mutate_field( 
    1110                                         newCand->expr.get(), &ast::Expr::result, 
     1110                                newCand->expr = ast::mutate_field(
     1111                                        newCand->expr.get(), &ast::Expr::result,
    11111112                                        renameTyVars( newCand->expr->result ) );
    1112                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     1113                                // add anonymous member interpretations whenever an aggregate value type is seen
    11131114                                // as a name expression
    11141115                                addAnonConversions( newCand );
     
    11201121                        // not sufficient to just pass `variableExpr` here, type might have changed since
    11211122                        // creation
    1122                         addCandidate( 
     1123                        addCandidate(
    11231124                                new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
    11241125                }
     
    11301131                void postvisit( const ast::SizeofExpr * sizeofExpr ) {
    11311132                        if ( sizeofExpr->type ) {
    1132                                 addCandidate( 
    1133                                         new ast::SizeofExpr{ 
    1134                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 
     1133                                addCandidate(
     1134                                        new ast::SizeofExpr{
     1135                                                sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
    11351136                                        tenv );
    11361137                        } else {
     
    11411142                                CandidateList winners = findMinCost( finder.candidates );
    11421143                                if ( winners.size() != 1 ) {
    1143                                         SemanticError( 
     1144                                        SemanticError(
    11441145                                                sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );
    11451146                                }
     
    11541155                void postvisit( const ast::AlignofExpr * alignofExpr ) {
    11551156                        if ( alignofExpr->type ) {
    1156                                 addCandidate( 
    1157                                         new ast::AlignofExpr{ 
    1158                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 
     1157                                addCandidate(
     1158                                        new ast::AlignofExpr{
     1159                                                alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
    11591160                                        tenv );
    11601161                        } else {
     
    11651166                                CandidateList winners = findMinCost( finder.candidates );
    11661167                                if ( winners.size() != 1 ) {
    1167                                         SemanticError( 
     1168                                        SemanticError(
    11681169                                                alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );
    11691170                                }
     
    11721173                                choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    11731174                                choice->cost = Cost::zero;
    1174                                 addCandidate( 
     1175                                addCandidate(
    11751176                                        *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );
    11761177                        }
     
    11851186                        for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {
    11861187                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );
    1187                                 addCandidate( 
     1188                                addCandidate(
    11881189                                        new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );
    11891190                        }
     
    12181219
    12191220                                        addCandidate(
    1220                                                 new ast::LogicalExpr{ 
     1221                                                new ast::LogicalExpr{
    12211222                                                        logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
    12221223                                                move( env ), move( open ), move( need ), r1->cost + r2->cost );
     
    12561257                                                ast::AssertionSet have;
    12571258
    1258                                                 // unify true and false results, then infer parameters to produce new 
     1259                                                // unify true and false results, then infer parameters to produce new
    12591260                                                // candidates
    12601261                                                ast::ptr< ast::Type > common;
    1261                                                 if ( 
    1262                                                         unify( 
    1263                                                                 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 
    1264                                                                 common ) 
     1262                                                if (
     1263                                                        unify(
     1264                                                                r2->expr->result, r3->expr->result, env, need, have, open, symtab,
     1265                                                                common )
    12651266                                                ) {
    12661267                                                        // generate typed expression
    1267                                                         ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 
     1268                                                        ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{
    12681269                                                                conditionalExpr->location, r1->expr, r2->expr, r3->expr };
    12691270                                                        newExpr->result = common ? common : r2->expr->result;
    12701271                                                        // convert both options to result type
    12711272                                                        Cost cost = r1->cost + r2->cost + r3->cost;
    1272                                                         newExpr->arg2 = computeExpressionConversionCost( 
     1273                                                        newExpr->arg2 = computeExpressionConversionCost(
    12731274                                                                newExpr->arg2, newExpr->result, symtab, env, cost );
    12741275                                                        newExpr->arg3 = computeExpressionConversionCost(
     
    12871288                        ast::TypeEnvironment env{ tenv };
    12881289                        ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
    1289                        
     1290
    12901291                        CandidateFinder finder2{ symtab, env };
    12911292                        finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
     
    13301331
    13311332                                        ast::ptr< ast::Type > common;
    1332                                         if ( 
    1333                                                 unify( 
    1334                                                         r1->expr->result, r2->expr->result, env, need, have, open, symtab, 
    1335                                                         common ) 
     1333                                        if (
     1334                                                unify(
     1335                                                        r1->expr->result, r2->expr->result, env, need, have, open, symtab,
     1336                                                        common )
    13361337                                        ) {
    13371338                                                // generate new expression
    1338                                                 ast::RangeExpr * newExpr = 
     1339                                                ast::RangeExpr * newExpr =
    13391340                                                        new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
    13401341                                                newExpr->result = common ? common : r1->expr->result;
    13411342                                                // add candidate
    13421343                                                CandidateRef newCand = std::make_shared<Candidate>(
    1343                                                         newExpr, move( env ), move( open ), move( need ), 
     1344                                                        newExpr, move( env ), move( open ), move( need ),
    13441345                                                        r1->cost + r2->cost );
    13451346                                                inferParameters( newCand, candidates );
     
    13501351
    13511352                void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
    1352                         std::vector< CandidateFinder > subCandidates = 
     1353                        std::vector< CandidateFinder > subCandidates =
    13531354                                selfFinder.findSubExprs( tupleExpr->exprs );
    13541355                        std::vector< CandidateList > possibilities;
     
    13701371
    13711372                                addCandidate(
    1372                                         new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 
     1373                                        new ast::TupleExpr{ tupleExpr->location, move( exprs ) },
    13731374                                        move( env ), move( open ), move( need ), sumCost( subs ) );
    13741375                        }
     
    14121413                                toType = SymTab::validateType( initExpr->location, toType, symtab );
    14131414                                toType = adjustExprType( toType, tenv, symtab );
    1414                                 // The call to find must occur inside this loop, otherwise polymorphic return 
    1415                                 // types are not bound to the initialization type, since return type variables are 
    1416                                 // only open for the duration of resolving the UntypedExpr. 
     1415                                // The call to find must occur inside this loop, otherwise polymorphic return
     1416                                // types are not bound to the initialization type, since return type variables are
     1417                                // only open for the duration of resolving the UntypedExpr.
    14171418                                CandidateFinder finder{ symtab, tenv, toType };
    14181419                                finder.find( initExpr->expr, ResolvMode::withAdjustment() );
     
    14261427                                        )
    14271428
    1428                                         // It is possible that a cast can throw away some values in a multiply-valued 
    1429                                         // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 
    1430                                         // the subexpression results that are cast directly. The candidate is invalid 
     1429                                        // It is possible that a cast can throw away some values in a multiply-valued
     1430                                        // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of
     1431                                        // the subexpression results that are cast directly. The candidate is invalid
    14311432                                        // if it has fewer results than there are types to cast to.
    14321433                                        int discardedValues = cand->expr->result->size() - toType->size();
     
    14351436                                        // unification run for side-effects
    14361437                                        unify( toType, cand->expr->result, env, need, have, open, symtab );
    1437                                         Cost thisCost = castCost( cand->expr->result, toType, symtab, env );
    1438                                        
     1438                                        Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1439                                                        symtab, env );
     1440
    14391441                                        if ( thisCost != Cost::infinity ) {
    14401442                                                // count one safe conversion for each value that is thrown away
    14411443                                                thisCost.incSafe( discardedValues );
    1442                                                 CandidateRef newCand = std::make_shared<Candidate>( 
    1443                                                         new ast::InitExpr{ 
    1444                                                                 initExpr->location, restructureCast( cand->expr, toType ), 
    1445                                                                 initAlt.designation }, 
     1444                                                CandidateRef newCand = std::make_shared<Candidate>(
     1445                                                        new ast::InitExpr{
     1446                                                                initExpr->location, restructureCast( cand->expr, toType ),
     1447                                                                initAlt.designation },
    14461448                                                        copy( cand->env ), move( open ), move( need ), cand->cost, thisCost );
    14471449                                                inferParameters( newCand, matches );
     
    14691471        };
    14701472
    1471         /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 
     1473        /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
    14721474        /// return type. Skips ambiguous candidates.
    14731475        CandidateList pruneCandidates( CandidateList & candidates ) {
     
    14861488                        {
    14871489                                ast::ptr< ast::Type > newType = candidate->expr->result;
     1490                                assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());
    14881491                                candidate->env.apply( newType );
    14891492                                mangleName = Mangle::mangle( newType );
     
    14941497                                if ( candidate->cost < found->second.candidate->cost ) {
    14951498                                        PRINT(
    1496                                                 std::cerr << "cost " << candidate->cost << " beats " 
     1499                                                std::cerr << "cost " << candidate->cost << " beats "
    14971500                                                        << found->second.candidate->cost << std::endl;
    14981501                                        )
     
    15001503                                        found->second = PruneStruct{ candidate };
    15011504                                } else if ( candidate->cost == found->second.candidate->cost ) {
    1502                                         // if one of the candidates contains a deleted identifier, can pick the other, 
    1503                                         // since deleted expressions should not be ambiguous if there is another option 
     1505                                        // if one of the candidates contains a deleted identifier, can pick the other,
     1506                                        // since deleted expressions should not be ambiguous if there is another option
    15041507                                        // that is at least as good
    15051508                                        if ( findDeletedExpr( candidate->expr ) ) {
     
    15151518                                } else {
    15161519                                        PRINT(
    1517                                                 std::cerr << "cost " << candidate->cost << " loses to " 
     1520                                                std::cerr << "cost " << candidate->cost << " loses to "
    15181521                                                        << found->second.candidate->cost << std::endl;
    15191522                                        )
     
    15301533
    15311534                        CandidateRef cand = target.second.candidate;
    1532                        
     1535
    15331536                        ast::ptr< ast::Type > newResult = cand->expr->result;
    15341537                        cand->env.applyFree( newResult );
    15351538                        cand->expr = ast::mutate_field(
    15361539                                cand->expr.get(), &ast::Expr::result, move( newResult ) );
    1537                        
     1540
    15381541                        out.emplace_back( cand );
    15391542                }
     
    15581561                std::vector< std::string > errors;
    15591562                for ( CandidateRef & candidate : candidates ) {
    1560                         satisfyAssertions( candidate, symtab, satisfied, errors );
     1563                        satisfyAssertions( candidate, localSyms, satisfied, errors );
    15611564                }
    15621565
     
    15831586
    15841587                CandidateList pruned = pruneCandidates( candidates );
    1585                
     1588
    15861589                if ( mode.failFast && pruned.empty() ) {
    15871590                        std::ostringstream stream;
     
    16021605                )
    16031606                PRINT(
    1604                         std::cerr << "there are " << candidates.size() << " alternatives after elimination" 
     1607                        std::cerr << "there are " << candidates.size() << " alternatives after elimination"
    16051608                                << std::endl;
    16061609                )
    16071610        }
    16081611
    1609         // adjust types after pruning so that types substituted by pruneAlternatives are correctly 
     1612        // adjust types after pruning so that types substituted by pruneAlternatives are correctly
    16101613        // adjusted
    16111614        if ( mode.adjust ) {
    16121615                for ( CandidateRef & r : candidates ) {
    1613                         r->expr = ast::mutate_field( 
    1614                                 r->expr.get(), &ast::Expr::result, 
    1615                                 adjustExprType( r->expr->result, r->env, symtab ) );
     1616                        r->expr = ast::mutate_field(
     1617                                r->expr.get(), &ast::Expr::result,
     1618                                adjustExprType( r->expr->result, r->env, localSyms ) );
    16161619                }
    16171620        }
     
    16251628}
    16261629
    1627 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 
    1628         const std::vector< ast::ptr< ast::Expr > > & xs 
     1630std::vector< CandidateFinder > CandidateFinder::findSubExprs(
     1631        const std::vector< ast::ptr< ast::Expr > > & xs
    16291632) {
    16301633        std::vector< CandidateFinder > out;
    16311634
    16321635        for ( const auto & x : xs ) {
    1633                 out.emplace_back( symtab, env );
     1636                out.emplace_back( localSyms, env );
    16341637                out.back().find( x, ResolvMode::withAdjustment() );
    1635                
     1638
    16361639                PRINT(
    16371640                        std::cerr << "findSubExprs" << std::endl;
Note: See TracChangeset for help on using the changeset viewer.