Ignore:
Timestamp:
Jan 7, 2021, 3:27:00 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
2b4daf2, 64aeca0
Parents:
3c64c668 (diff), eef8dfb (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 park_unpark

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CandidateFinder.cpp

    r3c64c668 r58fe85a  
    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
     
    4343#include "SymTab/Validate.h"      // for validateType
    4444#include "Tuples/Tuples.h"        // for handleTupleAssignment
     45#include "InitTweak/InitTweak.h"  // for getPointerBase
     46
     47#include "Common/Stats/Counter.h"
    4548
    4649#define PRINT( text ) if ( resolvep ) { text }
     
    5457                return new ast::CastExpr{ expr, expr->result->stripReferences() };
    5558        }
    56        
     59
    5760        return expr;
    5861}
     
    6164UniqueId globalResnSlot = 0;
    6265
    63 Cost computeConversionCost( 
    64         const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab,
    65         const ast::TypeEnvironment & env
     66Cost computeConversionCost(
     67        const ast::Type * argType, const ast::Type * paramType, bool argIsLvalue,
     68        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
    6669) {
    6770        PRINT(
     
    7477                std::cerr << std::endl;
    7578        )
    76         Cost convCost = conversionCost( argType, paramType, symtab, env );
     79        Cost convCost = conversionCost( argType, paramType, argIsLvalue, symtab, env );
    7780        PRINT(
    7881                std::cerr << std::endl << "cost is " << convCost << std::endl;
     
    107110
    108111        /// 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 
     112        const ast::Expr * computeExpressionConversionCost(
     113                const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost
    111114        ) {
    112                 Cost convCost = computeConversionCost( arg->result, paramType, symtab, env );
     115                Cost convCost = computeConversionCost(
     116                                arg->result, paramType, arg->get_lvalue(), symtab, env );
    113117                outCost += convCost;
    114118
    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 
     119                // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires
     120                // conversion. Ignore poly cost for now, since this requires resolution of the cast to
    117121                // infer parameters and this does not currently work for the reason stated below
    118122                Cost tmpCost = convCost;
     
    123127                        return new ast::CastExpr{ arg, newType };
    124128
    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, 
     129                        // xxx - *should* be able to resolve this cast, but at the moment pointers are not
     130                        // castable to zero_t, but are implicitly convertible. This is clearly inconsistent,
    127131                        // 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 
     132                        // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable,
     133                        // but it shouldn't be because this makes the conversion from DT* to DT* since
    130134                        // commontype(zero_t, DT*) is DT*, rather than nothing
    131135
    132136                        // CandidateFinder finder{ symtab, env };
    133137                        // finder.find( arg, ResolvMode::withAdjustment() );
    134                         // assertf( finder.candidates.size() > 0, 
     138                        // assertf( finder.candidates.size() > 0,
    135139                        //      "Somehow castable expression failed to find alternatives." );
    136                         // assertf( finder.candidates.size() == 1, 
     140                        // assertf( finder.candidates.size() == 1,
    137141                        //      "Somehow got multiple alternatives for known cast expression." );
    138142                        // return finder.candidates.front()->expr;
     
    143147
    144148        /// Computes conversion cost for a given candidate
    145         Cost computeApplicationConversionCost( 
    146                 CandidateRef cand, const ast::SymbolTable & symtab 
     149        Cost computeApplicationConversionCost(
     150                CandidateRef cand, const ast::SymbolTable & symtab
    147151        ) {
    148152                auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >();
     
    167171                                if ( function->isVarArgs ) {
    168172                                        convCost.incUnsafe();
    169                                         PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 
     173                                        PRINT( std::cerr << "end of params with varargs function: inc unsafe: "
    170174                                                << convCost << std::endl; ; )
    171175                                        // convert reference-typed expressions into value-typed expressions
    172                                         cand->expr = ast::mutate_field_index( 
    173                                                 appExpr, &ast::ApplicationExpr::args, i, 
     176                                        cand->expr = ast::mutate_field_index(
     177                                                appExpr, &ast::ApplicationExpr::args, i,
    174178                                                referenceToRvalueConversion( args[i], convCost ) );
    175179                                        continue;
     
    180184                                // Default arguments should be free - don't include conversion cost.
    181185                                // Unwrap them here because they are not relevant to the rest of the system
    182                                 cand->expr = ast::mutate_field_index( 
     186                                cand->expr = ast::mutate_field_index(
    183187                                        appExpr, &ast::ApplicationExpr::args, i, def->expr );
    184188                                ++param;
     
    187191
    188192                        // mark conversion cost and also specialization cost of param type
    189                         const ast::Type * paramType = (*param)->get_type();
    190                         cand->expr = ast::mutate_field_index( 
    191                                 appExpr, &ast::ApplicationExpr::args, i, 
    192                                 computeExpressionConversionCost( 
    193                                         args[i], paramType, symtab, cand->env, convCost ) );
    194                         convCost.decSpec( specCost( paramType ) );
     193                        // const ast::Type * paramType = (*param)->get_type();
     194                        cand->expr = ast::mutate_field_index(
     195                                appExpr, &ast::ApplicationExpr::args, i,
     196                                computeExpressionConversionCost(
     197                                        args[i], *param, symtab, cand->env, convCost ) );
     198                        convCost.decSpec( specCost( *param ) );
    195199                        ++param;  // can't be in for-loop update because of the continue
    196200                }
     
    198202                if ( param != params.end() ) return Cost::infinity;
    199203
    200                 // specialization cost of return types can't be accounted for directly, it disables 
     204                // specialization cost of return types can't be accounted for directly, it disables
    201205                // otherwise-identical calls, like this example based on auto-newline in the I/O lib:
    202206                //
     
    208212                // mark type variable and specialization cost of forall clause
    209213                convCost.incVar( function->forall.size() );
    210                 for ( const ast::TypeDecl * td : function->forall ) {
    211                         convCost.decSpec( td->assertions.size() );
    212                 }
     214                convCost.decSpec( function->assertions.size() );
    213215
    214216                return convCost;
    215217        }
    216218
    217         void makeUnifiableVars( 
    218                 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars,
    219                 ast::AssertionSet & need 
     219        void makeUnifiableVars(
     220                const ast::FunctionType * type, ast::OpenVarSet & unifiableVars,
     221                ast::AssertionSet & need
    220222        ) {
    221                 for ( const ast::TypeDecl * tyvar : type->forall ) {
    222                         unifiableVars[ tyvar->name ] = ast::TypeDecl::Data{ tyvar };
    223                         for ( const ast::DeclWithType * assn : tyvar->assertions ) {
    224                                 need[ assn ].isUsed = true;
    225                         }
     223                for ( auto & tyvar : type->forall ) {
     224                        unifiableVars[ *tyvar ] = ast::TypeDecl::Data{ tyvar->base };
     225                }
     226                for ( auto & assn : type->assertions ) {
     227                        need[ assn ].isUsed = true;
    226228                }
    227229        }
     
    254256
    255257                ArgPack()
    256                 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 
     258                : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ),
    257259                  tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    258                
    259                 ArgPack( 
    260                         const ast::TypeEnvironment & env, const ast::AssertionSet & need, 
     260
     261                ArgPack(
     262                        const ast::TypeEnvironment & env, const ast::AssertionSet & need,
    261263                        const ast::AssertionSet & have, const ast::OpenVarSet & open )
    262                 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 
     264                : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ),
    263265                  open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    264                
     266
    265267                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, 
     268                        std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env,
     269                        ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open,
     270                        unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero,
    269271                        unsigned nextExpl = 0, unsigned explAlt = 0 )
    270272                : parent(parent), expr( expr ), cost( cost ), env( move( env ) ), need( move( need ) ),
    271273                  have( move( have ) ), open( move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ),
    272274                  nextExpl( nextExpl ), explAlt( explAlt ) {}
    273                
     275
    274276                ArgPack(
    275                         const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 
     277                        const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need,
    276278                        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 ), 
     279                : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ),
     280                  need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ),
    279281                  tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {}
    280                
     282
    281283                /// true if this pack is in the middle of an exploded argument
    282284                bool hasExpl() const { return nextExpl > 0; }
     
    286288                        return args[ nextArg-1 ][ explAlt ];
    287289                }
    288                
     290
    289291                /// Ends a tuple expression, consolidating the appropriate args
    290292                void endTuple( const std::vector< ArgPack > & packs ) {
     
    307309
    308310        /// 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 
     311        bool instantiateArgument(
     312                const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args,
     313                std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,
     314                unsigned nTuples = 0
    313315        ) {
    314316                if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) {
     
    318320                                // xxx - dropping initializer changes behaviour from previous, but seems correct
    319321                                // ^^^ need to handle the case where a tuple has a default argument
    320                                 if ( ! instantiateArgument( 
     322                                if ( ! instantiateArgument(
    321323                                        type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;
    322324                                nTuples = 0;
     
    329331                } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) {
    330332                        // paramType is a ttype, consumes all remaining arguments
    331                        
     333
    332334                        // completed tuples; will be spliced to end of results to finish
    333335                        std::vector< ArgPack > finalResults{};
     
    342344                                for ( std::size_t i = genStart; i < genEnd; ++i ) {
    343345                                        unsigned nextArg = results[i].nextArg;
    344                                        
     346
    345347                                        // use next element of exploded tuple if present
    346348                                        if ( results[i].hasExpl() ) {
     
    352354                                                results.emplace_back(
    353355                                                        i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),
    354                                                         copy( results[i].need ), copy( results[i].have ), 
     356                                                        copy( results[i].need ), copy( results[i].have ),
    355357                                                        copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl,
    356358                                                        results[i].explAlt );
     
    370372                                                        // push empty tuple expression
    371373                                                        newResult.parent = i;
    372                                                         std::vector< ast::ptr< ast::Expr > > emptyList;
    373                                                         newResult.expr =
    374                                                                 new ast::TupleExpr{ CodeLocation{}, move( emptyList ) };
     374                                                        newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} };
    375375                                                        argType = newResult.expr->result;
    376376                                                } else {
     
    400400
    401401                                                // check unification for ttype before adding to final
    402                                                 if ( 
    403                                                         unify( 
     402                                                if (
     403                                                        unify(
    404404                                                                ttype, argType, newResult.env, newResult.need, newResult.have,
    405                                                                 newResult.open, symtab ) 
     405                                                                newResult.open, symtab )
    406406                                                ) {
    407407                                                        finalResults.emplace_back( move( newResult ) );
     
    424424                                                if ( expl.exprs.empty() ) {
    425425                                                        results.emplace_back(
    426                                                                 results[i], move( env ), copy( results[i].need ), 
     426                                                                results[i], move( env ), copy( results[i].need ),
    427427                                                                copy( results[i].have ), move( open ), nextArg + 1, expl.cost );
    428                                                        
     428
    429429                                                        continue;
    430430                                                }
     
    432432                                                // add new result
    433433                                                results.emplace_back(
    434                                                         i, expl.exprs.front(), move( env ), copy( results[i].need ), 
    435                                                         copy( results[i].have ), move( open ), nextArg + 1, nTuples, 
     434                                                        i, expl.exprs.front(), move( env ), copy( results[i].need ),
     435                                                        copy( results[i].have ), move( open ), nextArg + 1, nTuples,
    436436                                                        expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    437437                                        }
     
    479479
    480480                                        results.emplace_back(
    481                                                 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 
     481                                                i, expr, move( env ), move( need ), move( have ), move( open ), nextArg,
    482482                                                nTuples, Cost::zero, nextExpl, results[i].explAlt );
    483483                                }
     
    495495                                        if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {
    496496                                                results.emplace_back(
    497                                                         i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 
     497                                                        i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ),
    498498                                                        move( need ), move( have ), move( open ), nextArg, nTuples );
    499499                                        }
     
    517517                                if ( expl.exprs.empty() ) {
    518518                                        results.emplace_back(
    519                                                 results[i], move( env ), move( need ), move( have ), move( open ), 
     519                                                results[i], move( env ), move( need ), move( have ), move( open ),
    520520                                                nextArg + 1, expl.cost );
    521                                        
     521
    522522                                        continue;
    523523                                }
     
    539539                                        // add new result
    540540                                        results.emplace_back(
    541                                                 i, expr, move( env ), move( need ), move( have ), move( open ), 
     541                                                i, expr, move( env ), move( need ), move( have ), move( open ),
    542542                                                nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    543543                                }
     
    548548                genStart = genEnd;
    549549
    550                 return genEnd != results.size();
     550                return genEnd != results.size();  // were any new results added?
    551551        }
    552552
    553553        /// Generate a cast expression from `arg` to `toType`
    554         const ast::Expr * restructureCast( 
     554        const ast::Expr * restructureCast(
    555555                ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast
    556556        ) {
    557                 if ( 
    558                         arg->result->size() > 1 
    559                         && ! toType->isVoid() 
    560                         && ! dynamic_cast< const ast::ReferenceType * >( toType ) 
     557                if (
     558                        arg->result->size() > 1
     559                        && ! toType->isVoid()
     560                        && ! dynamic_cast< const ast::ReferenceType * >( toType )
    561561                ) {
    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 
     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
    566566                        // UniqueExpr ensures that the side effects will still be produced)
    567567                        if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {
    568                                 // expressions which may contain side effects require a single unique instance of 
     568                                // expressions which may contain side effects require a single unique instance of
    569569                                // the expression
    570570                                arg = new ast::UniqueExpr{ arg->location, arg };
     
    574574                                // cast each component
    575575                                ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i };
    576                                 components.emplace_back( 
     576                                components.emplace_back(
    577577                                        restructureCast( idx, toType->getComponent( i ), isGenerated ) );
    578578                        }
     
    594594
    595595        /// Actually visits expressions to find their candidate interpretations
    596         struct Finder final : public ast::WithShortCircuiting {
     596        class Finder final : public ast::WithShortCircuiting {
     597                const ast::SymbolTable & symtab;
     598        public:
     599                static size_t traceId;
    597600                CandidateFinder & selfFinder;
    598                 const ast::SymbolTable & symtab;
    599601                CandidateList & candidates;
    600602                const ast::TypeEnvironment & tenv;
    601603                ast::ptr< ast::Type > & targetType;
    602604
     605                enum Errors {
     606                        NotFound,
     607                        NoMatch,
     608                        ArgsToFew,
     609                        ArgsToMany,
     610                        RetsToFew,
     611                        RetsToMany,
     612                        NoReason
     613                };
     614
     615                struct {
     616                        Errors code = NotFound;
     617                } reason;
     618
    603619                Finder( CandidateFinder & f )
    604                 : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
     620                : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
    605621                  targetType( f.targetType ) {}
    606                
     622
    607623                void previsit( const ast::Node * ) { visit_children = false; }
    608624
     
    611627                void addCandidate( Args &&... args ) {
    612628                        candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } );
     629                        reason.code = NoReason;
    613630                }
    614631
     
    639656
    640657                /// Completes a function candidate with arguments located
    641                 void validateFunctionCandidate( 
    642                         const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 
    643                         CandidateList & out 
     658                void validateFunctionCandidate(
     659                        const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,
     660                        CandidateList & out
    644661                ) {
    645                         ast::ApplicationExpr * appExpr = 
     662                        ast::ApplicationExpr * appExpr =
    646663                                new ast::ApplicationExpr{ func->expr->location, func->expr };
    647664                        // sum cost and accumulate arguments
     
    657674                        appExpr->args = move( vargs );
    658675                        // build and validate new candidate
    659                         auto newCand = 
     676                        auto newCand =
    660677                                std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );
    661678                        PRINT(
     
    669686                /// Builds a list of candidates for a function, storing them in out
    670687                void makeFunctionCandidates(
    671                         const CandidateRef & func, const ast::FunctionType * funcType, 
     688                        const CandidateRef & func, const ast::FunctionType * funcType,
    672689                        const ExplodedArgs_new & args, CandidateList & out
    673690                ) {
     
    676693                        ast::TypeEnvironment funcEnv{ func->env };
    677694                        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
     695                        // add all type variables as open variables now so that those not used in the
     696                        // parameter list are still considered open
    680697                        funcEnv.add( funcType->forall );
    681698
    682699                        if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) {
    683700                                // attempt to narrow based on expected target type
    684                                 const ast::Type * returnType = funcType->returns.front()->get_type();
    685                                 if ( ! unify( 
    686                                         returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 
     701                                const ast::Type * returnType = funcType->returns.front();
     702                                if ( ! unify(
     703                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
    687704                                ) {
    688705                                        // unification failed, do not pursue this candidate
     
    696713                        std::size_t genStart = 0;
    697714
    698                         for ( const ast::DeclWithType * param : funcType->params ) {
    699                                 auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
    700                                 // Try adding the arguments corresponding to the current parameter to the existing
     715                        // xxx - how to handle default arg after change to ftype representation?
     716                        if (const ast::VariableExpr * varExpr = func->expr.as<ast::VariableExpr>()) {
     717                                if (const ast::FunctionDecl * funcDecl = varExpr->var.as<ast::FunctionDecl>()) {
     718                                        // function may have default args only if directly calling by name
     719                                        // must use types on candidate however, due to RenameVars substitution
     720                                        auto nParams = funcType->params.size();
     721
     722                                        for (size_t i=0; i<nParams; ++i) {
     723                                                auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>();
     724                                                if (!instantiateArgument(
     725                                                        funcType->params[i], obj->init, args, results, genStart, symtab)) return;
     726                                        }
     727                                        goto endMatch;
     728                                }
     729                        }
     730                        for ( const auto & param : funcType->params ) {
     731                                // Try adding the arguments corresponding to the current parameter to the existing
    701732                                // matches
    702                                 if ( ! instantiateArgument(
    703                                         obj->type, obj->init, args, results, genStart, symtab ) ) return;
    704                         }
    705 
     733                                // no default args for indirect calls
     734                                if ( ! instantiateArgument(
     735                                        param, nullptr, args, results, genStart, symtab ) ) return;
     736                        }
     737
     738                        endMatch:
    706739                        if ( funcType->isVarArgs ) {
    707740                                // append any unused arguments to vararg pack
     
    750783                                                        if ( expl.exprs.empty() ) {
    751784                                                                results.emplace_back(
    752                                                                         results[i], move( env ), copy( results[i].need ), 
    753                                                                         copy( results[i].have ), move( open ), nextArg + 1, 
     785                                                                        results[i], move( env ), copy( results[i].need ),
     786                                                                        copy( results[i].have ), move( open ), nextArg + 1,
    754787                                                                        expl.cost );
    755788
     
    760793                                                        results.emplace_back(
    761794                                                                i, expl.exprs.front(), move( env ), copy( results[i].need ),
    762                                                                 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 
     795                                                                copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost,
    763796                                                                expl.exprs.size() == 1 ? 0 : 1, j );
    764797                                                }
     
    780813                /// Adds implicit struct-conversions to the alternative list
    781814                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 
     815                        // adds anonymous member interpretations whenever an aggregate value type is seen.
     816                        // it's okay for the aggregate expression to have reference type -- cast it to the
    784817                        // base type to treat the aggregate as the referenced value
    785818                        ast::ptr< ast::Expr > aggrExpr( cand->expr );
    786819                        ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;
    787820                        cand->env.apply( aggrType );
    788                        
     821
    789822                        if ( aggrType.as< ast::ReferenceType >() ) {
    790823                                aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };
     
    799832
    800833                /// 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 
     834                void addAggMembers(
     835                        const ast::BaseInstType * aggrInst, const ast::Expr * expr,
     836                        const Candidate & cand, const Cost & addedCost, const std::string & name
    804837                ) {
    805838                        for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {
    806839                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );
    807                                 CandidateRef newCand = std::make_shared<Candidate>( 
     840                                CandidateRef newCand = std::make_shared<Candidate>(
    808841                                        cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
    809                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     842                                // add anonymous member interpretations whenever an aggregate value type is seen
    810843                                // as a member expression
    811844                                addAnonConversions( newCand );
     
    815848
    816849                /// 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 
     850                void addTupleMembers(
     851                        const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,
     852                        const Cost & addedCost, const ast::Expr * member
    820853                ) {
    821854                        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 
     855                                // get the value of the constant expression as an int, must be between 0 and the
    823856                                // length of the tuple to have meaning
    824857                                long long val = constantExpr->intValue();
    825858                                if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    826859                                        addCandidate(
    827                                                 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 
     860                                                cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },
    828861                                                addedCost );
    829862                                }
     
    832865
    833866                void postvisit( const ast::UntypedExpr * untypedExpr ) {
    834                         CandidateFinder funcFinder{ symtab, tenv };
    835                         funcFinder.find( untypedExpr->func, ResolvMode::withAdjustment() );
    836                         // short-circuit if no candidates
    837                         if ( funcFinder.candidates.empty() ) return;
    838 
    839                         std::vector< CandidateFinder > argCandidates =
     867                        std::vector< CandidateFinder > argCandidates =
    840868                                selfFinder.findSubExprs( untypedExpr->args );
    841                        
     869
    842870                        // take care of possible tuple assignments
    843871                        // if not tuple assignment, handled as normal function call
    844872                        Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates );
     873
     874                        CandidateFinder funcFinder{ symtab, tenv };
     875                        if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) {
     876                                auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);
     877                                if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) {
     878                                        assertf(!argCandidates.empty(), "special function call without argument");
     879                                        for (auto & firstArgCand: argCandidates[0]) {
     880                                                ast::ptr<ast::Type> argType = firstArgCand->expr->result;
     881                                                firstArgCand->env.apply(argType);
     882                                                // strip references
     883                                                // xxx - is this correct?
     884                                                while (argType.as<ast::ReferenceType>()) argType = argType.as<ast::ReferenceType>()->base;
     885
     886                                                // convert 1-tuple to plain type
     887                                                if (auto tuple = argType.as<ast::TupleType>()) {
     888                                                        if (tuple->size() == 1) {
     889                                                                argType = tuple->types[0];
     890                                                        }
     891                                                }
     892                                               
     893                                                // if argType is an unbound type parameter, all special functions need to be searched.
     894                                                if (isUnboundType(argType)) {
     895                                                        funcFinder.otypeKeys.clear();
     896                                                        break;
     897                                                }
     898
     899                                                if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer);
     900                                                else funcFinder.otypeKeys.insert(Mangle::mangle(argType, Mangle::NoGenericParams | Mangle::Type));
     901                                        }
     902                                }
     903                        }
     904                        // if candidates are already produced, do not fail
     905                        // xxx - is it possible that handleTupleAssignment and main finder both produce candidates?
     906                        // this means there exists ctor/assign functions with a tuple as first parameter.
     907                        ResolvMode mode = {
     908                                true, // adjust
     909                                !untypedExpr->func.as<ast::NameExpr>(), // prune if not calling by name
     910                                selfFinder.candidates.empty() // failfast if other options are not found
     911                        };
     912                        funcFinder.find( untypedExpr->func, mode );
     913                        // short-circuit if no candidates
     914                        // if ( funcFinder.candidates.empty() ) return;
     915
     916                        reason.code = NoMatch;
    845917
    846918                        // find function operators
     
    877949                                                if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    878950                                                        CandidateRef newFunc{ new Candidate{ *func } };
    879                                                         newFunc->expr = 
     951                                                        newFunc->expr =
    880952                                                                referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    881953                                                        makeFunctionCandidates( newFunc, function, argExpansions, found );
    882954                                                }
    883                                         } else if ( 
    884                                                 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 
     955                                        } else if (
     956                                                auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
    885957                                        ) {
    886                                                 if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) {
     958                                                if ( const ast::EqvClass * clz = func->env.lookup( *inst ) ) {
    887959                                                        if ( auto function = clz->bound.as< ast::FunctionType >() ) {
    888960                                                                CandidateRef newFunc{ new Candidate{ *func } };
    889                                                                 newFunc->expr = 
     961                                                                newFunc->expr =
    890962                                                                        referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    891963                                                                makeFunctionCandidates( newFunc, function, argExpansions, found );
     
    901973                                std::vector< ExplodedArg > funcE;
    902974                                funcE.reserve( funcFinder.candidates.size() );
    903                                 for ( const CandidateRef & func : funcFinder ) { 
     975                                for ( const CandidateRef & func : funcFinder ) {
    904976                                        funcE.emplace_back( *func, symtab );
    905977                                }
     
    913985                                                        if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    914986                                                                CandidateRef newOp{ new Candidate{ *op} };
    915                                                                 newOp->expr = 
     987                                                                newOp->expr =
    916988                                                                        referenceToRvalueConversion( newOp->expr, newOp->cost );
    917989                                                                makeFunctionCandidates( newOp, function, argExpansions, found );
     
    922994                        }
    923995
    924                         // Implement SFINAE; resolution errors are only errors if there aren't any non-error 
     996                        // Implement SFINAE; resolution errors are only errors if there aren't any non-error
    925997                        // candidates
    926998                        if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
     
    9341006                                        auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
    9351007                                        auto function = pointer->base.strict_as< ast::FunctionType >();
    936                                        
     1008
    9371009                                        std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;
    9381010                                        std::cerr << "parameters are:" << std::endl;
     
    9571029                        promoteCvtCost( winners );
    9581030
    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 
     1031                        // function may return a struct/union value, in which case we need to add candidates
     1032                        // for implicit conversions to each of the anonymous members, which must happen after
    9611033                        // `findMinCost`, since anon conversions are never the cheapest
    9621034                        for ( const CandidateRef & c : winners ) {
     
    9661038
    9671039                        if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
    968                                 // If resolution is unsuccessful with a target type, try again without, since it 
     1040                                // If resolution is unsuccessful with a target type, try again without, since it
    9691041                                // will sometimes succeed when it wouldn't with a target type binding.
    9701042                                // For example:
     
    9831055                /// true if expression is an lvalue
    9841056                static bool isLvalue( const ast::Expr * x ) {
    985                         return x->result && ( x->result->is_lvalue() || x->result.as< ast::ReferenceType >() );
     1057                        return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() );
    9861058                }
    9871059
     
    9891061                        CandidateFinder finder{ symtab, tenv };
    9901062                        finder.find( addressExpr->arg );
     1063
     1064                        if( finder.candidates.empty() ) return;
     1065
     1066                        reason.code = NoMatch;
     1067
    9911068                        for ( CandidateRef & r : finder.candidates ) {
    9921069                                if ( ! isLvalue( r->expr ) ) continue;
     
    10031080                        assert( toType );
    10041081                        toType = resolveTypeof( toType, symtab );
    1005                         toType = SymTab::validateType( castExpr->location, toType, symtab );
     1082                        // toType = SymTab::validateType( castExpr->location, toType, symtab );
    10061083                        toType = adjustExprType( toType, tenv, symtab );
    10071084
    10081085                        CandidateFinder finder{ symtab, tenv, toType };
    10091086                        finder.find( castExpr->arg, ResolvMode::withAdjustment() );
     1087
     1088                        if( !finder.candidates.empty() ) reason.code = NoMatch;
    10101089
    10111090                        CandidateList matches;
     
    10161095                                cand->env.extractOpenVars( open );
    10171096
    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 
     1097                                // It is possible that a cast can throw away some values in a multiply-valued
     1098                                // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the
     1099                                // subexpression results that are cast directly. The candidate is invalid if it
    10211100                                // has fewer results than there are types to cast to.
    10221101                                int discardedValues = cand->expr->result->size() - toType->size();
     
    10251104                                // unification run for side-effects
    10261105                                unify( toType, cand->expr->result, cand->env, need, have, open, symtab );
    1027                                 Cost thisCost = castCost( cand->expr->result, toType, symtab, cand->env );
     1106                                Cost thisCost =
     1107                                        (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast)
     1108                            ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env )
     1109                            : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env );
     1110
    10281111                                PRINT(
    10291112                                        std::cerr << "working on cast with result: " << toType << std::endl;
     
    10371120                                        // count one safe conversion for each value that is thrown away
    10381121                                        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, 
     1122                                        CandidateRef newCand = std::make_shared<Candidate>(
     1123                                                restructureCast( cand->expr, toType, castExpr->isGenerated ),
     1124                                                copy( cand->env ), move( open ), move( need ), cand->cost,
    10421125                                                cand->cost + thisCost );
    10431126                                        inferParameters( newCand, matches );
     
    10571140                        finder.find( castExpr->arg, ResolvMode::withoutPrune() );
    10581141                        for ( CandidateRef & r : finder.candidates ) {
    1059                                 addCandidate( 
    1060                                         *r, 
     1142                                addCandidate(
     1143                                        *r,
    10611144                                        new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
    10621145                        }
     1146                }
     1147
     1148                void postvisit( const ast::KeywordCastExpr * castExpr ) {
     1149                        const auto & loc = castExpr->location;
     1150                        assertf( castExpr->result, "Cast target should have been set in Validate." );
     1151                        auto ref = castExpr->result.strict_as<ast::ReferenceType>();
     1152                        auto inst = ref->base.strict_as<ast::StructInstType>();
     1153                        auto target = inst->base.get();
     1154
     1155                        CandidateFinder finder{ symtab, tenv };
     1156
     1157                        auto pick_alternatives = [target, this](CandidateList & found, bool expect_ref) {
     1158                                for(auto & cand : found) {
     1159                                        const ast::Type * expr = cand->expr->result.get();
     1160                                        if(expect_ref) {
     1161                                                auto res = dynamic_cast<const ast::ReferenceType*>(expr);
     1162                                                if(!res) { continue; }
     1163                                                expr = res->base.get();
     1164                                        }
     1165
     1166                                        if(auto insttype = dynamic_cast<const ast::TypeInstType*>(expr)) {
     1167                                                auto td = cand->env.lookup(*insttype);
     1168                                                if(!td) { continue; }
     1169                                                expr = td->bound.get();
     1170                                        }
     1171
     1172                                        if(auto base = dynamic_cast<const ast::StructInstType*>(expr)) {
     1173                                                if(base->base == target) {
     1174                                                        candidates.push_back( std::move(cand) );
     1175                                                        reason.code = NoReason;
     1176                                                }
     1177                                        }
     1178                                }
     1179                        };
     1180
     1181                        try {
     1182                                // Attempt 1 : turn (thread&)X into ($thread&)X.__thrd
     1183                                // Clone is purely for memory management
     1184                                std::unique_ptr<const ast::Expr> tech1 { new ast::UntypedMemberExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.field), castExpr->arg) };
     1185
     1186                                // don't prune here, since it's guaranteed all alternatives will have the same type
     1187                                finder.find( tech1.get(), ResolvMode::withoutPrune() );
     1188                                pick_alternatives(finder.candidates, false);
     1189
     1190                                return;
     1191                        } catch(SemanticErrorException & ) {}
     1192
     1193                        // Fallback : turn (thread&)X into ($thread&)get_thread(X)
     1194                        std::unique_ptr<const ast::Expr> fallback { ast::UntypedExpr::createDeref(loc,  new ast::UntypedExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.getter), { castExpr->arg })) };
     1195                        // don't prune here, since it's guaranteed all alternatives will have the same type
     1196                        finder.find( fallback.get(), ResolvMode::withoutPrune() );
     1197
     1198                        pick_alternatives(finder.candidates, true);
     1199
     1200                        // Whatever happens here, we have no more fallbacks
    10631201                }
    10641202
     
    10671205                        aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    10681206                        for ( CandidateRef & agg : aggFinder.candidates ) {
    1069                                 // it's okay for the aggregate expression to have reference type -- cast it to the 
     1207                                // it's okay for the aggregate expression to have reference type -- cast it to the
    10701208                                // base type to treat the aggregate as the referenced value
    10711209                                Cost addedCost = Cost::zero;
     
    10741212                                // find member of the given type
    10751213                                if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {
    1076                                         addAggMembers( 
     1214                                        addAggMembers(
    10771215                                                structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10781216                                } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {
    1079                                         addAggMembers( 
     1217                                        addAggMembers(
    10801218                                                unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10811219                                } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {
     
    10901228
    10911229                void postvisit( const ast::NameExpr * nameExpr ) {
    1092                         std::vector< ast::SymbolTable::IdData > declList = symtab.lookupId( nameExpr->name );
     1230                        std::vector< ast::SymbolTable::IdData > declList;
     1231                        if (!selfFinder.otypeKeys.empty()) {
     1232                                auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);
     1233                                assertf(kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS, "special lookup with non-special target: %s", nameExpr->name.c_str());
     1234
     1235                                for (auto & otypeKey: selfFinder.otypeKeys) {
     1236                                        auto result = symtab.specialLookupId(kind, otypeKey);
     1237                                        declList.insert(declList.end(), std::make_move_iterator(result.begin()), std::make_move_iterator(result.end()));
     1238                                }
     1239                        }
     1240                        else {
     1241                                declList = symtab.lookupId( nameExpr->name );
     1242                        }
    10931243                        PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
     1244
     1245                        if( declList.empty() ) return;
     1246
     1247                        reason.code = NoMatch;
     1248
    10941249                        for ( auto & data : declList ) {
    10951250                                Cost cost = Cost::zero;
     
    10971252
    10981253                                CandidateRef newCand = std::make_shared<Candidate>(
    1099                                         newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 
     1254                                        newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
    11001255                                        cost );
    11011256                                PRINT(
     
    11071262                                        std::cerr << std::endl;
    11081263                                )
    1109                                 newCand->expr = ast::mutate_field( 
    1110                                         newCand->expr.get(), &ast::Expr::result, 
     1264                                newCand->expr = ast::mutate_field(
     1265                                        newCand->expr.get(), &ast::Expr::result,
    11111266                                        renameTyVars( newCand->expr->result ) );
    1112                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     1267                                // add anonymous member interpretations whenever an aggregate value type is seen
    11131268                                // as a name expression
    11141269                                addAnonConversions( newCand );
     
    11201275                        // not sufficient to just pass `variableExpr` here, type might have changed since
    11211276                        // creation
    1122                         addCandidate( 
     1277                        addCandidate(
    11231278                                new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
    11241279                }
     
    11301285                void postvisit( const ast::SizeofExpr * sizeofExpr ) {
    11311286                        if ( sizeofExpr->type ) {
    1132                                 addCandidate( 
    1133                                         new ast::SizeofExpr{ 
    1134                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 
     1287                                addCandidate(
     1288                                        new ast::SizeofExpr{
     1289                                                sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
    11351290                                        tenv );
    11361291                        } else {
     
    11411296                                CandidateList winners = findMinCost( finder.candidates );
    11421297                                if ( winners.size() != 1 ) {
    1143                                         SemanticError( 
     1298                                        SemanticError(
    11441299                                                sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );
    11451300                                }
     
    11541309                void postvisit( const ast::AlignofExpr * alignofExpr ) {
    11551310                        if ( alignofExpr->type ) {
    1156                                 addCandidate( 
    1157                                         new ast::AlignofExpr{ 
    1158                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 
     1311                                addCandidate(
     1312                                        new ast::AlignofExpr{
     1313                                                alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
    11591314                                        tenv );
    11601315                        } else {
     
    11651320                                CandidateList winners = findMinCost( finder.candidates );
    11661321                                if ( winners.size() != 1 ) {
    1167                                         SemanticError( 
     1322                                        SemanticError(
    11681323                                                alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );
    11691324                                }
     
    11721327                                choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    11731328                                choice->cost = Cost::zero;
    1174                                 addCandidate( 
     1329                                addCandidate(
    11751330                                        *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );
    11761331                        }
     
    11781333
    11791334                void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) {
    1180                         const ast::ReferenceToType * aggInst;
     1335                        const ast::BaseInstType * aggInst;
    11811336                        if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ;
    11821337                        else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ;
     
    11851340                        for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {
    11861341                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );
    1187                                 addCandidate( 
     1342                                addCandidate(
    11881343                                        new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );
    11891344                        }
     
    12061361                        finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );
    12071362                        if ( finder2.candidates.empty() ) return;
     1363
     1364                        reason.code = NoMatch;
    12081365
    12091366                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    12181375
    12191376                                        addCandidate(
    1220                                                 new ast::LogicalExpr{ 
     1377                                                new ast::LogicalExpr{
    12211378                                                        logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
    12221379                                                move( env ), move( open ), move( need ), r1->cost + r2->cost );
     
    12401397                        finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );
    12411398                        if ( finder3.candidates.empty() ) return;
     1399
     1400                        reason.code = NoMatch;
    12421401
    12431402                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    12561415                                                ast::AssertionSet have;
    12571416
    1258                                                 // unify true and false results, then infer parameters to produce new 
     1417                                                // unify true and false results, then infer parameters to produce new
    12591418                                                // candidates
    12601419                                                ast::ptr< ast::Type > common;
    1261                                                 if ( 
    1262                                                         unify( 
    1263                                                                 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 
    1264                                                                 common ) 
     1420                                                if (
     1421                                                        unify(
     1422                                                                r2->expr->result, r3->expr->result, env, need, have, open, symtab,
     1423                                                                common )
    12651424                                                ) {
    12661425                                                        // generate typed expression
    1267                                                         ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 
     1426                                                        ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{
    12681427                                                                conditionalExpr->location, r1->expr, r2->expr, r3->expr };
    12691428                                                        newExpr->result = common ? common : r2->expr->result;
    12701429                                                        // convert both options to result type
    12711430                                                        Cost cost = r1->cost + r2->cost + r3->cost;
    1272                                                         newExpr->arg2 = computeExpressionConversionCost( 
     1431                                                        newExpr->arg2 = computeExpressionConversionCost(
    12731432                                                                newExpr->arg2, newExpr->result, symtab, env, cost );
    12741433                                                        newExpr->arg3 = computeExpressionConversionCost(
     
    12871446                        ast::TypeEnvironment env{ tenv };
    12881447                        ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
    1289                        
     1448
    12901449                        CandidateFinder finder2{ symtab, env };
    12911450                        finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
     
    13171476                        finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );
    13181477                        if ( finder2.candidates.empty() ) return;
     1478
     1479                        reason.code = NoMatch;
    13191480
    13201481                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    13301491
    13311492                                        ast::ptr< ast::Type > common;
    1332                                         if ( 
    1333                                                 unify( 
    1334                                                         r1->expr->result, r2->expr->result, env, need, have, open, symtab, 
    1335                                                         common ) 
     1493                                        if (
     1494                                                unify(
     1495                                                        r1->expr->result, r2->expr->result, env, need, have, open, symtab,
     1496                                                        common )
    13361497                                        ) {
    13371498                                                // generate new expression
    1338                                                 ast::RangeExpr * newExpr = 
     1499                                                ast::RangeExpr * newExpr =
    13391500                                                        new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
    13401501                                                newExpr->result = common ? common : r1->expr->result;
    13411502                                                // add candidate
    13421503                                                CandidateRef newCand = std::make_shared<Candidate>(
    1343                                                         newExpr, move( env ), move( open ), move( need ), 
     1504                                                        newExpr, move( env ), move( open ), move( need ),
    13441505                                                        r1->cost + r2->cost );
    13451506                                                inferParameters( newCand, candidates );
     
    13501511
    13511512                void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
    1352                         std::vector< CandidateFinder > subCandidates = 
     1513                        std::vector< CandidateFinder > subCandidates =
    13531514                                selfFinder.findSubExprs( tupleExpr->exprs );
    13541515                        std::vector< CandidateList > possibilities;
     
    13701531
    13711532                                addCandidate(
    1372                                         new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 
     1533                                        new ast::TupleExpr{ tupleExpr->location, move( exprs ) },
    13731534                                        move( env ), move( open ), move( need ), sumCost( subs ) );
    13741535                        }
     
    14101571                                // calculate target type
    14111572                                const ast::Type * toType = resolveTypeof( initAlt.type, symtab );
    1412                                 toType = SymTab::validateType( initExpr->location, toType, symtab );
     1573                                // toType = SymTab::validateType( initExpr->location, toType, symtab );
    14131574                                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. 
     1575                                // The call to find must occur inside this loop, otherwise polymorphic return
     1576                                // types are not bound to the initialization type, since return type variables are
     1577                                // only open for the duration of resolving the UntypedExpr.
    14171578                                CandidateFinder finder{ symtab, tenv, toType };
    14181579                                finder.find( initExpr->expr, ResolvMode::withAdjustment() );
    14191580                                for ( CandidateRef & cand : finder.candidates ) {
     1581                                        if(reason.code == NotFound) reason.code = NoMatch;
     1582
    14201583                                        ast::TypeEnvironment env{ cand->env };
    14211584                                        ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;
     
    14261589                                        )
    14271590
    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 
     1591                                        // It is possible that a cast can throw away some values in a multiply-valued
     1592                                        // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of
     1593                                        // the subexpression results that are cast directly. The candidate is invalid
    14311594                                        // if it has fewer results than there are types to cast to.
    14321595                                        int discardedValues = cand->expr->result->size() - toType->size();
     
    14341597
    14351598                                        // unification run for side-effects
    1436                                         unify( toType, cand->expr->result, env, need, have, open, symtab );
    1437                                         Cost thisCost = castCost( cand->expr->result, toType, symtab, env );
    1438                                        
     1599                                        bool canUnify = unify( toType, cand->expr->result, env, need, have, open, symtab );
     1600                                        (void) canUnify;
     1601                                        Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1602                                                symtab, env );
     1603                                        PRINT(
     1604                                                Cost legacyCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1605                                                        symtab, env );
     1606                                                std::cerr << "Considering initialization:";
     1607                                                std::cerr << std::endl << "  FROM: " << cand->expr->result << std::endl;
     1608                                                std::cerr << std::endl << "  TO: "   << toType             << std::endl;
     1609                                                std::cerr << std::endl << "  Unification " << (canUnify ? "succeeded" : "failed");
     1610                                                std::cerr << std::endl << "  Legacy cost " << legacyCost;
     1611                                                std::cerr << std::endl << "  New cost " << thisCost;
     1612                                                std::cerr << std::endl;
     1613                                        )
    14391614                                        if ( thisCost != Cost::infinity ) {
    14401615                                                // count one safe conversion for each value that is thrown away
    14411616                                                thisCost.incSafe( discardedValues );
    1442                                                 CandidateRef newCand = std::make_shared<Candidate>( 
    1443                                                         new ast::InitExpr{ 
    1444                                                                 initExpr->location, restructureCast( cand->expr, toType ), 
    1445                                                                 initAlt.designation }, 
    1446                                                         copy( cand->env ), move( open ), move( need ), cand->cost, thisCost );
     1617                                                CandidateRef newCand = std::make_shared<Candidate>(
     1618                                                        new ast::InitExpr{
     1619                                                                initExpr->location, restructureCast( cand->expr, toType ),
     1620                                                                initAlt.designation },
     1621                                                        move(env), move( open ), move( need ), cand->cost, thisCost );
    14471622                                                inferParameters( newCand, matches );
    14481623                                        }
    14491624                                }
     1625
    14501626                        }
    14511627
     
    14691645        };
    14701646
    1471         /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
     1647        // size_t Finder::traceId = Stats::Heap::new_stacktrace_id("Finder");
     1648        /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
    14721649        /// return type. Skips ambiguous candidates.
    1473         CandidateList pruneCandidates( CandidateList & candidates ) {
    1474                 struct PruneStruct {
    1475                         CandidateRef candidate;
    1476                         bool ambiguous;
    1477 
    1478                         PruneStruct() = default;
    1479                         PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {}
    1480                 };
    1481 
    1482                 // find lowest-cost candidate for each type
    1483                 std::unordered_map< std::string, PruneStruct > selected;
    1484                 for ( CandidateRef & candidate : candidates ) {
    1485                         std::string mangleName;
     1650
     1651} // anonymous namespace
     1652
     1653bool CandidateFinder::pruneCandidates( CandidateList & candidates, CandidateList & out, std::vector<std::string> & errors ) {
     1654        struct PruneStruct {
     1655                CandidateRef candidate;
     1656                bool ambiguous;
     1657
     1658                PruneStruct() = default;
     1659                PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {}
     1660        };
     1661
     1662        // find lowest-cost candidate for each type
     1663        std::unordered_map< std::string, PruneStruct > selected;
     1664        // attempt to skip satisfyAssertions on more expensive alternatives if better options have been found
     1665        std::sort(candidates.begin(), candidates.end(), [](const CandidateRef & x, const CandidateRef & y){return x->cost < y->cost;});
     1666        for ( CandidateRef & candidate : candidates ) {
     1667                std::string mangleName;
     1668                {
     1669                        ast::ptr< ast::Type > newType = candidate->expr->result;
     1670                        assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());
     1671                        candidate->env.apply( newType );
     1672                        mangleName = Mangle::mangle( newType );
     1673                }
     1674
     1675                auto found = selected.find( mangleName );
     1676                if (found != selected.end() && found->second.candidate->cost < candidate->cost) {
     1677                        PRINT(
     1678                                std::cerr << "cost " << candidate->cost << " loses to "
     1679                                        << found->second.candidate->cost << std::endl;
     1680                        )
     1681                        continue;
     1682                }
     1683
     1684                // xxx - when do satisfyAssertions produce more than 1 result?
     1685                // this should only happen when initial result type contains
     1686                // unbound type parameters, then it should never be pruned by
     1687                // the previous step, since renameTyVars guarantees the mangled name
     1688                // is unique.
     1689                CandidateList satisfied;
     1690                bool needRecomputeKey = false;
     1691                if (candidate->need.empty()) {
     1692                        satisfied.emplace_back(candidate);
     1693                }
     1694                else {
     1695                        satisfyAssertions(candidate, localSyms, satisfied, errors);
     1696                        needRecomputeKey = true;
     1697                }
     1698
     1699                for (auto & newCand : satisfied) {
     1700                        // recomputes type key, if satisfyAssertions changed it
     1701                        if (needRecomputeKey)
    14861702                        {
    1487                                 ast::ptr< ast::Type > newType = candidate->expr->result;
    1488                                 candidate->env.apply( newType );
     1703                                ast::ptr< ast::Type > newType = newCand->expr->result;
     1704                                assertf(newCand->expr->result, "Result of expression %p for candidate is null", newCand->expr.get());
     1705                                newCand->env.apply( newType );
    14891706                                mangleName = Mangle::mangle( newType );
    14901707                        }
    1491 
    14921708                        auto found = selected.find( mangleName );
    14931709                        if ( found != selected.end() ) {
    1494                                 if ( candidate->cost < found->second.candidate->cost ) {
     1710                                if ( newCand->cost < found->second.candidate->cost ) {
    14951711                                        PRINT(
    1496                                                 std::cerr << "cost " << candidate->cost << " beats "
     1712                                                std::cerr << "cost " << newCand->cost << " beats "
    14971713                                                        << found->second.candidate->cost << std::endl;
    14981714                                        )
    14991715
    1500                                         found->second = PruneStruct{ candidate };
    1501                                 } 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 
     1716                                        found->second = PruneStruct{ newCand };
     1717                                } else if ( newCand->cost == found->second.candidate->cost ) {
     1718                                        // if one of the candidates contains a deleted identifier, can pick the other,
     1719                                        // since deleted expressions should not be ambiguous if there is another option
    15041720                                        // that is at least as good
    1505                                         if ( findDeletedExpr( candidate->expr ) ) {
     1721                                        if ( findDeletedExpr( newCand->expr ) ) {
    15061722                                                // do nothing
    15071723                                                PRINT( std::cerr << "candidate is deleted" << std::endl; )
    15081724                                        } else if ( findDeletedExpr( found->second.candidate->expr ) ) {
    15091725                                                PRINT( std::cerr << "current is deleted" << std::endl; )
    1510                                                 found->second = PruneStruct{ candidate };
     1726                                                found->second = PruneStruct{ newCand };
    15111727                                        } else {
    15121728                                                PRINT( std::cerr << "marking ambiguous" << std::endl; )
    15131729                                                found->second.ambiguous = true;
    15141730                                        }
    1515                                 } else {
     1731                                } else {
     1732                                        // xxx - can satisfyAssertions increase the cost?
    15161733                                        PRINT(
    1517                                                 std::cerr << "cost " << candidate->cost << " loses to "
     1734                                                std::cerr << "cost " << newCand->cost << " loses to "
    15181735                                                        << found->second.candidate->cost << std::endl;
    1519                                         )
     1736                                        )       
    15201737                                }
    15211738                        } else {
    1522                                 selected.emplace_hint( found, mangleName, candidate );
    1523                         }
    1524                 }
    1525 
    1526                 // report unambiguous min-cost candidates
    1527                 CandidateList out;
    1528                 for ( auto & target : selected ) {
    1529                         if ( target.second.ambiguous ) continue;
    1530 
    1531                         CandidateRef cand = target.second.candidate;
    1532                        
    1533                         ast::ptr< ast::Type > newResult = cand->expr->result;
    1534                         cand->env.applyFree( newResult );
    1535                         cand->expr = ast::mutate_field(
    1536                                 cand->expr.get(), &ast::Expr::result, move( newResult ) );
    1537                        
    1538                         out.emplace_back( cand );
    1539                 }
    1540                 return out;
     1739                                selected.emplace_hint( found, mangleName, newCand );
     1740                        }
     1741                }
    15411742        }
    15421743
    1543 } // anonymous namespace
     1744        // report unambiguous min-cost candidates
     1745        // CandidateList out;
     1746        for ( auto & target : selected ) {
     1747                if ( target.second.ambiguous ) continue;
     1748
     1749                CandidateRef cand = target.second.candidate;
     1750
     1751                ast::ptr< ast::Type > newResult = cand->expr->result;
     1752                cand->env.applyFree( newResult );
     1753                cand->expr = ast::mutate_field(
     1754                        cand->expr.get(), &ast::Expr::result, move( newResult ) );
     1755
     1756                out.emplace_back( cand );
     1757        }
     1758        // if everything is lost in satisfyAssertions, report the error
     1759        return !selected.empty();
     1760}
    15441761
    15451762void CandidateFinder::find( const ast::Expr * expr, ResolvMode mode ) {
     
    15491766
    15501767        if ( mode.failFast && candidates.empty() ) {
    1551                 SemanticError( expr, "No reasonable alternatives for expression " );
     1768                switch(finder.core.reason.code) {
     1769                case Finder::NotFound:
     1770                        { SemanticError( expr, "No alternatives for expression " ); break; }
     1771                case Finder::NoMatch:
     1772                        { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; }
     1773                case Finder::ArgsToFew:
     1774                case Finder::ArgsToMany:
     1775                case Finder::RetsToFew:
     1776                case Finder::RetsToMany:
     1777                case Finder::NoReason:
     1778                default:
     1779                        { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); }
     1780                }
    15521781        }
    15531782
     1783        /*
    15541784        if ( mode.satisfyAssns || mode.prune ) {
    15551785                // trim candidates to just those where the assertions are satisfiable
     
    15581788                std::vector< std::string > errors;
    15591789                for ( CandidateRef & candidate : candidates ) {
    1560                         satisfyAssertions( candidate, symtab, satisfied, errors );
     1790                        satisfyAssertions( candidate, localSyms, satisfied, errors );
    15611791                }
    15621792
     
    15741804                candidates = move( satisfied );
    15751805        }
     1806        */
    15761807
    15771808        if ( mode.prune ) {
     
    15821813                )
    15831814
    1584                 CandidateList pruned = pruneCandidates( candidates );
    1585                
     1815                CandidateList pruned;
     1816                std::vector<std::string> errors;
     1817                bool found = pruneCandidates( candidates, pruned, errors );
     1818
    15861819                if ( mode.failFast && pruned.empty() ) {
    15871820                        std::ostringstream stream;
    1588                         CandidateList winners = findMinCost( candidates );
    1589                         stream << "Cannot choose between " << winners.size() << " alternatives for "
    1590                                 "expression\n";
    1591                         ast::print( stream, expr );
    1592                         stream << " Alternatives are:\n";
    1593                         print( stream, winners, 1 );
    1594                         SemanticError( expr->location, stream.str() );
     1821                        if (found) {           
     1822                                CandidateList winners = findMinCost( candidates );
     1823                                stream << "Cannot choose between " << winners.size() << " alternatives for "
     1824                                        "expression\n";
     1825                                ast::print( stream, expr );
     1826                                stream << " Alternatives are:\n";
     1827                                print( stream, winners, 1 );
     1828                                SemanticError( expr->location, stream.str() );
     1829                        }
     1830                        else {
     1831                                stream << "No alternatives with satisfiable assertions for " << expr << "\n";
     1832                                for ( const auto& err : errors ) {
     1833                                        stream << err;
     1834                                }
     1835                                SemanticError( expr->location, stream.str() );
     1836                        }
    15951837                }
    15961838
     
    16021844                )
    16031845                PRINT(
    1604                         std::cerr << "there are " << candidates.size() << " alternatives after elimination" 
     1846                        std::cerr << "there are " << candidates.size() << " alternatives after elimination"
    16051847                                << std::endl;
    16061848                )
    16071849        }
    16081850
    1609         // adjust types after pruning so that types substituted by pruneAlternatives are correctly 
     1851        // adjust types after pruning so that types substituted by pruneAlternatives are correctly
    16101852        // adjusted
    16111853        if ( mode.adjust ) {
    16121854                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 ) );
     1855                        r->expr = ast::mutate_field(
     1856                                r->expr.get(), &ast::Expr::result,
     1857                                adjustExprType( r->expr->result, r->env, localSyms ) );
    16161858                }
    16171859        }
     
    16251867}
    16261868
    1627 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 
    1628         const std::vector< ast::ptr< ast::Expr > > & xs 
     1869std::vector< CandidateFinder > CandidateFinder::findSubExprs(
     1870        const std::vector< ast::ptr< ast::Expr > > & xs
    16291871) {
    16301872        std::vector< CandidateFinder > out;
    16311873
    16321874        for ( const auto & x : xs ) {
    1633                 out.emplace_back( symtab, env );
     1875                out.emplace_back( localSyms, env );
    16341876                out.back().find( x, ResolvMode::withAdjustment() );
    1635                
     1877
    16361878                PRINT(
    16371879                        std::cerr << "findSubExprs" << std::endl;
Note: See TracChangeset for help on using the changeset viewer.