Changeset 4c925cd for src/ResolvExpr


Ignore:
Timestamp:
Aug 14, 2020, 11:40:04 AM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
5715d43, fa5e0112
Parents:
309d814 (diff), badd22f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

Location:
src/ResolvExpr
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AdjustExprType.cc

    r309d814 r4c925cd  
    100100
    101101namespace {
    102         struct AdjustExprType_new final : public ast::WithShortCircuiting {
     102        class AdjustExprType_new final : public ast::WithShortCircuiting {
     103                const ast::SymbolTable & symtab;
     104        public:
    103105                const ast::TypeEnvironment & tenv;
    104                 const ast::SymbolTable & symtab;
    105106
    106107                AdjustExprType_new( const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
    107                 : tenv( e ), symtab( syms ) {}
     108                : symtab( syms ), tenv( e ) {}
    108109
    109                 void premutate( const ast::VoidType * ) { visit_children = false; }
    110                 void premutate( const ast::BasicType * ) { visit_children = false; }
    111                 void premutate( const ast::PointerType * ) { visit_children = false; }
    112                 void premutate( const ast::ArrayType * ) { visit_children = false; }
    113                 void premutate( const ast::FunctionType * ) { visit_children = false; }
    114                 void premutate( const ast::StructInstType * ) { visit_children = false; }
    115                 void premutate( const ast::UnionInstType * ) { visit_children = false; }
    116                 void premutate( const ast::EnumInstType * ) { visit_children = false; }
    117                 void premutate( const ast::TraitInstType * ) { visit_children = false; }
    118                 void premutate( const ast::TypeInstType * ) { visit_children = false; }
    119                 void premutate( const ast::TupleType * ) { visit_children = false; }
    120                 void premutate( const ast::VarArgsType * ) { visit_children = false; }
    121                 void premutate( const ast::ZeroType * ) { visit_children = false; }
    122                 void premutate( const ast::OneType * ) { visit_children = false; }
     110                void previsit( const ast::VoidType * ) { visit_children = false; }
     111                void previsit( const ast::BasicType * ) { visit_children = false; }
     112                void previsit( const ast::PointerType * ) { visit_children = false; }
     113                void previsit( const ast::ArrayType * ) { visit_children = false; }
     114                void previsit( const ast::FunctionType * ) { visit_children = false; }
     115                void previsit( const ast::StructInstType * ) { visit_children = false; }
     116                void previsit( const ast::UnionInstType * ) { visit_children = false; }
     117                void previsit( const ast::EnumInstType * ) { visit_children = false; }
     118                void previsit( const ast::TraitInstType * ) { visit_children = false; }
     119                void previsit( const ast::TypeInstType * ) { visit_children = false; }
     120                void previsit( const ast::TupleType * ) { visit_children = false; }
     121                void previsit( const ast::VarArgsType * ) { visit_children = false; }
     122                void previsit( const ast::ZeroType * ) { visit_children = false; }
     123                void previsit( const ast::OneType * ) { visit_children = false; }
    123124
    124                 const ast::Type * postmutate( const ast::ArrayType * at ) {
     125                const ast::Type * postvisit( const ast::ArrayType * at ) {
    125126                        return new ast::PointerType{ at->base, at->qualifiers };
    126127                }
    127128
    128                 const ast::Type * postmutate( const ast::FunctionType * ft ) {
     129                const ast::Type * postvisit( const ast::FunctionType * ft ) {
    129130                        return new ast::PointerType{ ft };
    130131                }
    131132
    132                 const ast::Type * postmutate( const ast::TypeInstType * inst ) {
     133                const ast::Type * postvisit( const ast::TypeInstType * inst ) {
    133134                        // replace known function-type-variables with pointer-to-function
    134135                        if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name ) ) {
  • src/ResolvExpr/Candidate.hpp

    r309d814 r4c925cd  
    5151
    5252        Candidate( const ast::Expr * x, const ast::TypeEnvironment & e )
    53         : expr( x ), cost( Cost::zero ), cvtCost( Cost::zero ), env( e ), open(), need() {}
     53        : expr( x ), cost( Cost::zero ), cvtCost( Cost::zero ), env( e ), open(), need() {
     54                assert(x->result);
     55        }
    5456
    5557        Candidate( const Candidate & o, const ast::Expr * x, const Cost & addedCost = Cost::zero )
    5658        : expr( x ), cost( o.cost + addedCost ), cvtCost( Cost::zero ), env( o.env ), open( o.open ),
    57           need( o.need ) {}
     59          need( o.need ) {
     60                assert(x->result);
     61        }
    5862
    5963        Candidate(
    60                 const ast::Expr * x, const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 
     64                const ast::Expr * x, const ast::TypeEnvironment & e, const ast::OpenVarSet & o,
    6165                const ast::AssertionSet & n, const Cost & c, const Cost & cvt = Cost::zero )
    62         : expr( x ), cost( c ), cvtCost( cvt ), env( e ), open( o ), need( n.begin(), n.end() ) {}
     66        : expr( x ), cost( c ), cvtCost( cvt ), env( e ), open( o ), need( n.begin(), n.end() ) {
     67                assert(x->result);
     68        }
    6369
    6470        Candidate(
     
    6672                ast::AssertionSet && n, const Cost & c, const Cost & cvt = Cost::zero )
    6773        : expr( x ), cost( c ), cvtCost( cvt ), env( std::move( e ) ), open( std::move( o ) ),
    68           need( n.begin(), n.end() ) {}
     74          need( n.begin(), n.end() ) {
     75                assert(x->result);
     76        }
    6977};
    7078
  • src/ResolvExpr/CandidateFinder.cpp

    r309d814 r4c925cd  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed Jun 5 14:30:00 2019
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Wed Jun 5 14:30:00 2019
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Oct  1 14:55:00 2019
     13// Update Count     : 2
    1414//
    1515
     
    5454                return new ast::CastExpr{ expr, expr->result->stripReferences() };
    5555        }
    56        
     56
    5757        return expr;
    5858}
     
    6161UniqueId globalResnSlot = 0;
    6262
    63 Cost computeConversionCost( 
    64         const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab,
    65         const ast::TypeEnvironment & env
     63Cost computeConversionCost(
     64        const ast::Type * argType, const ast::Type * paramType, bool argIsLvalue,
     65        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
    6666) {
    6767        PRINT(
     
    7474                std::cerr << std::endl;
    7575        )
    76         Cost convCost = conversionCost( argType, paramType, symtab, env );
     76        Cost convCost = conversionCost( argType, paramType, argIsLvalue, symtab, env );
    7777        PRINT(
    7878                std::cerr << std::endl << "cost is " << convCost << std::endl;
     
    107107
    108108        /// Computes conversion cost for a given expression to a given type
    109         const ast::Expr * computeExpressionConversionCost( 
    110                 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 
     109        const ast::Expr * computeExpressionConversionCost(
     110                const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost
    111111        ) {
    112                 Cost convCost = computeConversionCost( arg->result, paramType, symtab, env );
     112                Cost convCost = computeConversionCost(
     113                                arg->result, paramType, arg->get_lvalue(), symtab, env );
    113114                outCost += convCost;
    114115
    115                 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires 
    116                 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 
     116                // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires
     117                // conversion. Ignore poly cost for now, since this requires resolution of the cast to
    117118                // infer parameters and this does not currently work for the reason stated below
    118119                Cost tmpCost = convCost;
     
    123124                        return new ast::CastExpr{ arg, newType };
    124125
    125                         // xxx - *should* be able to resolve this cast, but at the moment pointers are not 
    126                         // castable to zero_t, but are implicitly convertible. This is clearly inconsistent, 
     126                        // xxx - *should* be able to resolve this cast, but at the moment pointers are not
     127                        // castable to zero_t, but are implicitly convertible. This is clearly inconsistent,
    127128                        // once this is fixed it should be possible to resolve the cast.
    128                         // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable, 
    129                         // but it shouldn't be because this makes the conversion from DT* to DT* since 
     129                        // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable,
     130                        // but it shouldn't be because this makes the conversion from DT* to DT* since
    130131                        // commontype(zero_t, DT*) is DT*, rather than nothing
    131132
    132133                        // CandidateFinder finder{ symtab, env };
    133134                        // finder.find( arg, ResolvMode::withAdjustment() );
    134                         // assertf( finder.candidates.size() > 0, 
     135                        // assertf( finder.candidates.size() > 0,
    135136                        //      "Somehow castable expression failed to find alternatives." );
    136                         // assertf( finder.candidates.size() == 1, 
     137                        // assertf( finder.candidates.size() == 1,
    137138                        //      "Somehow got multiple alternatives for known cast expression." );
    138139                        // return finder.candidates.front()->expr;
     
    143144
    144145        /// Computes conversion cost for a given candidate
    145         Cost computeApplicationConversionCost( 
    146                 CandidateRef cand, const ast::SymbolTable & symtab 
     146        Cost computeApplicationConversionCost(
     147                CandidateRef cand, const ast::SymbolTable & symtab
    147148        ) {
    148149                auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >();
     
    167168                                if ( function->isVarArgs ) {
    168169                                        convCost.incUnsafe();
    169                                         PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 
     170                                        PRINT( std::cerr << "end of params with varargs function: inc unsafe: "
    170171                                                << convCost << std::endl; ; )
    171172                                        // convert reference-typed expressions into value-typed expressions
    172                                         cand->expr = ast::mutate_field_index( 
    173                                                 appExpr, &ast::ApplicationExpr::args, i, 
     173                                        cand->expr = ast::mutate_field_index(
     174                                                appExpr, &ast::ApplicationExpr::args, i,
    174175                                                referenceToRvalueConversion( args[i], convCost ) );
    175176                                        continue;
     
    180181                                // Default arguments should be free - don't include conversion cost.
    181182                                // Unwrap them here because they are not relevant to the rest of the system
    182                                 cand->expr = ast::mutate_field_index( 
     183                                cand->expr = ast::mutate_field_index(
    183184                                        appExpr, &ast::ApplicationExpr::args, i, def->expr );
    184185                                ++param;
     
    188189                        // mark conversion cost and also specialization cost of param type
    189190                        const ast::Type * paramType = (*param)->get_type();
    190                         cand->expr = ast::mutate_field_index( 
    191                                 appExpr, &ast::ApplicationExpr::args, i, 
    192                                 computeExpressionConversionCost( 
     191                        cand->expr = ast::mutate_field_index(
     192                                appExpr, &ast::ApplicationExpr::args, i,
     193                                computeExpressionConversionCost(
    193194                                        args[i], paramType, symtab, cand->env, convCost ) );
    194195                        convCost.decSpec( specCost( paramType ) );
     
    198199                if ( param != params.end() ) return Cost::infinity;
    199200
    200                 // specialization cost of return types can't be accounted for directly, it disables 
     201                // specialization cost of return types can't be accounted for directly, it disables
    201202                // otherwise-identical calls, like this example based on auto-newline in the I/O lib:
    202203                //
     
    215216        }
    216217
    217         void makeUnifiableVars( 
    218                 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars, 
    219                 ast::AssertionSet & need 
     218        void makeUnifiableVars(
     219                const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars,
     220                ast::AssertionSet & need
    220221        ) {
    221222                for ( const ast::TypeDecl * tyvar : type->forall ) {
     
    254255
    255256                ArgPack()
    256                 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 
     257                : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ),
    257258                  tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    258                
    259                 ArgPack( 
    260                         const ast::TypeEnvironment & env, const ast::AssertionSet & need, 
     259
     260                ArgPack(
     261                        const ast::TypeEnvironment & env, const ast::AssertionSet & need,
    261262                        const ast::AssertionSet & have, const ast::OpenVarSet & open )
    262                 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 
     263                : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ),
    263264                  open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    264                
     265
    265266                ArgPack(
    266                         std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env, 
    267                         ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open, 
    268                         unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero, 
     267                        std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env,
     268                        ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open,
     269                        unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero,
    269270                        unsigned nextExpl = 0, unsigned explAlt = 0 )
    270271                : parent(parent), expr( expr ), cost( cost ), env( move( env ) ), need( move( need ) ),
    271272                  have( move( have ) ), open( move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ),
    272273                  nextExpl( nextExpl ), explAlt( explAlt ) {}
    273                
     274
    274275                ArgPack(
    275                         const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 
     276                        const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need,
    276277                        ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added )
    277                 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ), 
    278                   need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ), 
     278                : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ),
     279                  need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ),
    279280                  tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {}
    280                
     281
    281282                /// true if this pack is in the middle of an exploded argument
    282283                bool hasExpl() const { return nextExpl > 0; }
     
    286287                        return args[ nextArg-1 ][ explAlt ];
    287288                }
    288                
     289
    289290                /// Ends a tuple expression, consolidating the appropriate args
    290291                void endTuple( const std::vector< ArgPack > & packs ) {
     
    307308
    308309        /// Instantiates an argument to match a parameter, returns false if no matching results left
    309         bool instantiateArgument( 
    310                 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args, 
    311                 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 
    312                 unsigned nTuples = 0 
     310        bool instantiateArgument(
     311                const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args,
     312                std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,
     313                unsigned nTuples = 0
    313314        ) {
    314315                if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) {
     
    318319                                // xxx - dropping initializer changes behaviour from previous, but seems correct
    319320                                // ^^^ need to handle the case where a tuple has a default argument
    320                                 if ( ! instantiateArgument( 
     321                                if ( ! instantiateArgument(
    321322                                        type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;
    322323                                nTuples = 0;
     
    329330                } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) {
    330331                        // paramType is a ttype, consumes all remaining arguments
    331                        
     332
    332333                        // completed tuples; will be spliced to end of results to finish
    333334                        std::vector< ArgPack > finalResults{};
     
    342343                                for ( std::size_t i = genStart; i < genEnd; ++i ) {
    343344                                        unsigned nextArg = results[i].nextArg;
    344                                        
     345
    345346                                        // use next element of exploded tuple if present
    346347                                        if ( results[i].hasExpl() ) {
     
    352353                                                results.emplace_back(
    353354                                                        i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),
    354                                                         copy( results[i].need ), copy( results[i].have ), 
     355                                                        copy( results[i].need ), copy( results[i].have ),
    355356                                                        copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl,
    356357                                                        results[i].explAlt );
     
    370371                                                        // push empty tuple expression
    371372                                                        newResult.parent = i;
    372                                                         std::vector< ast::ptr< ast::Expr > > emptyList;
    373                                                         newResult.expr =
    374                                                                 new ast::TupleExpr{ CodeLocation{}, move( emptyList ) };
     373                                                        newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} };
    375374                                                        argType = newResult.expr->result;
    376375                                                } else {
     
    400399
    401400                                                // check unification for ttype before adding to final
    402                                                 if ( 
    403                                                         unify( 
     401                                                if (
     402                                                        unify(
    404403                                                                ttype, argType, newResult.env, newResult.need, newResult.have,
    405                                                                 newResult.open, symtab ) 
     404                                                                newResult.open, symtab )
    406405                                                ) {
    407406                                                        finalResults.emplace_back( move( newResult ) );
     
    424423                                                if ( expl.exprs.empty() ) {
    425424                                                        results.emplace_back(
    426                                                                 results[i], move( env ), copy( results[i].need ), 
     425                                                                results[i], move( env ), copy( results[i].need ),
    427426                                                                copy( results[i].have ), move( open ), nextArg + 1, expl.cost );
    428                                                        
     427
    429428                                                        continue;
    430429                                                }
     
    432431                                                // add new result
    433432                                                results.emplace_back(
    434                                                         i, expl.exprs.front(), move( env ), copy( results[i].need ), 
    435                                                         copy( results[i].have ), move( open ), nextArg + 1, nTuples, 
     433                                                        i, expl.exprs.front(), move( env ), copy( results[i].need ),
     434                                                        copy( results[i].have ), move( open ), nextArg + 1, nTuples,
    436435                                                        expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    437436                                        }
     
    479478
    480479                                        results.emplace_back(
    481                                                 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 
     480                                                i, expr, move( env ), move( need ), move( have ), move( open ), nextArg,
    482481                                                nTuples, Cost::zero, nextExpl, results[i].explAlt );
    483482                                }
     
    495494                                        if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {
    496495                                                results.emplace_back(
    497                                                         i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 
     496                                                        i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ),
    498497                                                        move( need ), move( have ), move( open ), nextArg, nTuples );
    499498                                        }
     
    517516                                if ( expl.exprs.empty() ) {
    518517                                        results.emplace_back(
    519                                                 results[i], move( env ), move( need ), move( have ), move( open ), 
     518                                                results[i], move( env ), move( need ), move( have ), move( open ),
    520519                                                nextArg + 1, expl.cost );
    521                                        
     520
    522521                                        continue;
    523522                                }
     
    539538                                        // add new result
    540539                                        results.emplace_back(
    541                                                 i, expr, move( env ), move( need ), move( have ), move( open ), 
     540                                                i, expr, move( env ), move( need ), move( have ), move( open ),
    542541                                                nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    543542                                }
     
    548547                genStart = genEnd;
    549548
    550                 return genEnd != results.size();
     549                return genEnd != results.size();  // were any new results added?
    551550        }
    552551
    553552        /// Generate a cast expression from `arg` to `toType`
    554         const ast::Expr * restructureCast( 
     553        const ast::Expr * restructureCast(
    555554                ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast
    556555        ) {
    557                 if ( 
    558                         arg->result->size() > 1 
    559                         && ! toType->isVoid() 
    560                         && ! dynamic_cast< const ast::ReferenceType * >( toType ) 
     556                if (
     557                        arg->result->size() > 1
     558                        && ! toType->isVoid()
     559                        && ! dynamic_cast< const ast::ReferenceType * >( toType )
    561560                ) {
    562                         // Argument is a tuple and the target type is neither void nor a reference. Cast each 
    563                         // member of the tuple to its corresponding target type, producing the tuple of those 
    564                         // cast expressions. If there are more components of the tuple than components in the 
    565                         // target type, then excess components do not come out in the result expression (but 
     561                        // Argument is a tuple and the target type is neither void nor a reference. Cast each
     562                        // member of the tuple to its corresponding target type, producing the tuple of those
     563                        // cast expressions. If there are more components of the tuple than components in the
     564                        // target type, then excess components do not come out in the result expression (but
    566565                        // UniqueExpr ensures that the side effects will still be produced)
    567566                        if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {
    568                                 // expressions which may contain side effects require a single unique instance of 
     567                                // expressions which may contain side effects require a single unique instance of
    569568                                // the expression
    570569                                arg = new ast::UniqueExpr{ arg->location, arg };
     
    574573                                // cast each component
    575574                                ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i };
    576                                 components.emplace_back( 
     575                                components.emplace_back(
    577576                                        restructureCast( idx, toType->getComponent( i ), isGenerated ) );
    578577                        }
     
    594593
    595594        /// Actually visits expressions to find their candidate interpretations
    596         struct Finder final : public ast::WithShortCircuiting {
     595        class Finder final : public ast::WithShortCircuiting {
     596                const ast::SymbolTable & symtab;
     597        public:
     598                static size_t traceId;
    597599                CandidateFinder & selfFinder;
    598                 const ast::SymbolTable & symtab;
    599600                CandidateList & candidates;
    600601                const ast::TypeEnvironment & tenv;
    601602                ast::ptr< ast::Type > & targetType;
    602603
     604                enum Errors {
     605                        NotFound,
     606                        NoMatch,
     607                        ArgsToFew,
     608                        ArgsToMany,
     609                        RetsToFew,
     610                        RetsToMany,
     611                        NoReason
     612                };
     613
     614                struct {
     615                        Errors code = NotFound;
     616                } reason;
     617
    603618                Finder( CandidateFinder & f )
    604                 : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
     619                : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
    605620                  targetType( f.targetType ) {}
    606                
     621
    607622                void previsit( const ast::Node * ) { visit_children = false; }
    608623
     
    611626                void addCandidate( Args &&... args ) {
    612627                        candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } );
     628                        reason.code = NoReason;
    613629                }
    614630
     
    639655
    640656                /// Completes a function candidate with arguments located
    641                 void validateFunctionCandidate( 
    642                         const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 
    643                         CandidateList & out 
     657                void validateFunctionCandidate(
     658                        const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,
     659                        CandidateList & out
    644660                ) {
    645                         ast::ApplicationExpr * appExpr = 
     661                        ast::ApplicationExpr * appExpr =
    646662                                new ast::ApplicationExpr{ func->expr->location, func->expr };
    647663                        // sum cost and accumulate arguments
     
    657673                        appExpr->args = move( vargs );
    658674                        // build and validate new candidate
    659                         auto newCand = 
     675                        auto newCand =
    660676                                std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );
    661677                        PRINT(
     
    669685                /// Builds a list of candidates for a function, storing them in out
    670686                void makeFunctionCandidates(
    671                         const CandidateRef & func, const ast::FunctionType * funcType, 
     687                        const CandidateRef & func, const ast::FunctionType * funcType,
    672688                        const ExplodedArgs_new & args, CandidateList & out
    673689                ) {
     
    676692                        ast::TypeEnvironment funcEnv{ func->env };
    677693                        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
     694                        // add all type variables as open variables now so that those not used in the
     695                        // parameter list are still considered open
    680696                        funcEnv.add( funcType->forall );
    681697
     
    683699                                // attempt to narrow based on expected target type
    684700                                const ast::Type * returnType = funcType->returns.front()->get_type();
    685                                 if ( ! unify( 
    686                                         returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 
     701                                if ( ! unify(
     702                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
    687703                                ) {
    688704                                        // unification failed, do not pursue this candidate
     
    698714                        for ( const ast::DeclWithType * param : funcType->params ) {
    699715                                auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
    700                                 // Try adding the arguments corresponding to the current parameter to the existing 
     716                                // Try adding the arguments corresponding to the current parameter to the existing
    701717                                // matches
    702                                 if ( ! instantiateArgument( 
     718                                if ( ! instantiateArgument(
    703719                                        obj->type, obj->init, args, results, genStart, symtab ) ) return;
    704720                        }
     
    750766                                                        if ( expl.exprs.empty() ) {
    751767                                                                results.emplace_back(
    752                                                                         results[i], move( env ), copy( results[i].need ), 
    753                                                                         copy( results[i].have ), move( open ), nextArg + 1, 
     768                                                                        results[i], move( env ), copy( results[i].need ),
     769                                                                        copy( results[i].have ), move( open ), nextArg + 1,
    754770                                                                        expl.cost );
    755771
     
    760776                                                        results.emplace_back(
    761777                                                                i, expl.exprs.front(), move( env ), copy( results[i].need ),
    762                                                                 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 
     778                                                                copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost,
    763779                                                                expl.exprs.size() == 1 ? 0 : 1, j );
    764780                                                }
     
    780796                /// Adds implicit struct-conversions to the alternative list
    781797                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 
     798                        // adds anonymous member interpretations whenever an aggregate value type is seen.
     799                        // it's okay for the aggregate expression to have reference type -- cast it to the
    784800                        // base type to treat the aggregate as the referenced value
    785801                        ast::ptr< ast::Expr > aggrExpr( cand->expr );
    786802                        ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;
    787803                        cand->env.apply( aggrType );
    788                        
     804
    789805                        if ( aggrType.as< ast::ReferenceType >() ) {
    790806                                aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };
     
    799815
    800816                /// 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 
     817                void addAggMembers(
     818                        const ast::ReferenceToType * aggrInst, const ast::Expr * expr,
     819                        const Candidate & cand, const Cost & addedCost, const std::string & name
    804820                ) {
    805821                        for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {
    806822                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );
    807                                 CandidateRef newCand = std::make_shared<Candidate>( 
     823                                CandidateRef newCand = std::make_shared<Candidate>(
    808824                                        cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
    809                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     825                                // add anonymous member interpretations whenever an aggregate value type is seen
    810826                                // as a member expression
    811827                                addAnonConversions( newCand );
     
    815831
    816832                /// 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 
     833                void addTupleMembers(
     834                        const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,
     835                        const Cost & addedCost, const ast::Expr * member
    820836                ) {
    821837                        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 
     838                                // get the value of the constant expression as an int, must be between 0 and the
    823839                                // length of the tuple to have meaning
    824840                                long long val = constantExpr->intValue();
    825841                                if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    826842                                        addCandidate(
    827                                                 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 
     843                                                cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },
    828844                                                addedCost );
    829845                                }
     
    837853                        if ( funcFinder.candidates.empty() ) return;
    838854
    839                         std::vector< CandidateFinder > argCandidates =
     855                        reason.code = NoMatch;
     856
     857                        std::vector< CandidateFinder > argCandidates =
    840858                                selfFinder.findSubExprs( untypedExpr->args );
    841                        
     859
    842860                        // take care of possible tuple assignments
    843861                        // if not tuple assignment, handled as normal function call
     
    877895                                                if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    878896                                                        CandidateRef newFunc{ new Candidate{ *func } };
    879                                                         newFunc->expr = 
     897                                                        newFunc->expr =
    880898                                                                referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    881899                                                        makeFunctionCandidates( newFunc, function, argExpansions, found );
    882900                                                }
    883                                         } else if ( 
    884                                                 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 
     901                                        } else if (
     902                                                auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
    885903                                        ) {
    886904                                                if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) {
    887905                                                        if ( auto function = clz->bound.as< ast::FunctionType >() ) {
    888906                                                                CandidateRef newFunc{ new Candidate{ *func } };
    889                                                                 newFunc->expr = 
     907                                                                newFunc->expr =
    890908                                                                        referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    891909                                                                makeFunctionCandidates( newFunc, function, argExpansions, found );
     
    901919                                std::vector< ExplodedArg > funcE;
    902920                                funcE.reserve( funcFinder.candidates.size() );
    903                                 for ( const CandidateRef & func : funcFinder ) { 
     921                                for ( const CandidateRef & func : funcFinder ) {
    904922                                        funcE.emplace_back( *func, symtab );
    905923                                }
     
    913931                                                        if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    914932                                                                CandidateRef newOp{ new Candidate{ *op} };
    915                                                                 newOp->expr = 
     933                                                                newOp->expr =
    916934                                                                        referenceToRvalueConversion( newOp->expr, newOp->cost );
    917935                                                                makeFunctionCandidates( newOp, function, argExpansions, found );
     
    922940                        }
    923941
    924                         // Implement SFINAE; resolution errors are only errors if there aren't any non-error 
     942                        // Implement SFINAE; resolution errors are only errors if there aren't any non-error
    925943                        // candidates
    926944                        if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
     
    934952                                        auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
    935953                                        auto function = pointer->base.strict_as< ast::FunctionType >();
    936                                        
     954
    937955                                        std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;
    938956                                        std::cerr << "parameters are:" << std::endl;
     
    957975                        promoteCvtCost( winners );
    958976
    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 
     977                        // function may return a struct/union value, in which case we need to add candidates
     978                        // for implicit conversions to each of the anonymous members, which must happen after
    961979                        // `findMinCost`, since anon conversions are never the cheapest
    962980                        for ( const CandidateRef & c : winners ) {
     
    966984
    967985                        if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
    968                                 // If resolution is unsuccessful with a target type, try again without, since it 
     986                                // If resolution is unsuccessful with a target type, try again without, since it
    969987                                // will sometimes succeed when it wouldn't with a target type binding.
    970988                                // For example:
     
    9831001                /// true if expression is an lvalue
    9841002                static bool isLvalue( const ast::Expr * x ) {
    985                         return x->result && ( x->result->is_lvalue() || x->result.as< ast::ReferenceType >() );
     1003                        return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() );
    9861004                }
    9871005
     
    9891007                        CandidateFinder finder{ symtab, tenv };
    9901008                        finder.find( addressExpr->arg );
     1009
     1010                        if( finder.candidates.empty() ) return;
     1011
     1012                        reason.code = NoMatch;
     1013
    9911014                        for ( CandidateRef & r : finder.candidates ) {
    9921015                                if ( ! isLvalue( r->expr ) ) continue;
     
    10091032                        finder.find( castExpr->arg, ResolvMode::withAdjustment() );
    10101033
     1034                        if( !finder.candidates.empty() ) reason.code = NoMatch;
     1035
    10111036                        CandidateList matches;
    10121037                        for ( CandidateRef & cand : finder.candidates ) {
     
    10161041                                cand->env.extractOpenVars( open );
    10171042
    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 
     1043                                // It is possible that a cast can throw away some values in a multiply-valued
     1044                                // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the
     1045                                // subexpression results that are cast directly. The candidate is invalid if it
    10211046                                // has fewer results than there are types to cast to.
    10221047                                int discardedValues = cand->expr->result->size() - toType->size();
     
    10251050                                // unification run for side-effects
    10261051                                unify( toType, cand->expr->result, cand->env, need, have, open, symtab );
    1027                                 Cost thisCost = castCost( cand->expr->result, toType, symtab, cand->env );
     1052                                Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1053                                                symtab, cand->env );
    10281054                                PRINT(
    10291055                                        std::cerr << "working on cast with result: " << toType << std::endl;
     
    10371063                                        // count one safe conversion for each value that is thrown away
    10381064                                        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, 
     1065                                        CandidateRef newCand = std::make_shared<Candidate>(
     1066                                                restructureCast( cand->expr, toType, castExpr->isGenerated ),
     1067                                                copy( cand->env ), move( open ), move( need ), cand->cost,
    10421068                                                cand->cost + thisCost );
    10431069                                        inferParameters( newCand, matches );
     
    10571083                        finder.find( castExpr->arg, ResolvMode::withoutPrune() );
    10581084                        for ( CandidateRef & r : finder.candidates ) {
    1059                                 addCandidate( 
    1060                                         *r, 
     1085                                addCandidate(
     1086                                        *r,
    10611087                                        new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
    10621088                        }
     
    10671093                        aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    10681094                        for ( CandidateRef & agg : aggFinder.candidates ) {
    1069                                 // it's okay for the aggregate expression to have reference type -- cast it to the 
     1095                                // it's okay for the aggregate expression to have reference type -- cast it to the
    10701096                                // base type to treat the aggregate as the referenced value
    10711097                                Cost addedCost = Cost::zero;
     
    10741100                                // find member of the given type
    10751101                                if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {
    1076                                         addAggMembers( 
     1102                                        addAggMembers(
    10771103                                                structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10781104                                } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {
    1079                                         addAggMembers( 
     1105                                        addAggMembers(
    10801106                                                unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10811107                                } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {
     
    10921118                        std::vector< ast::SymbolTable::IdData > declList = symtab.lookupId( nameExpr->name );
    10931119                        PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
     1120                        if( declList.empty() ) return;
     1121
     1122                        reason.code = NoMatch;
     1123
    10941124                        for ( auto & data : declList ) {
    10951125                                Cost cost = Cost::zero;
     
    10971127
    10981128                                CandidateRef newCand = std::make_shared<Candidate>(
    1099                                         newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 
     1129                                        newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
    11001130                                        cost );
    11011131                                PRINT(
     
    11071137                                        std::cerr << std::endl;
    11081138                                )
    1109                                 newCand->expr = ast::mutate_field( 
    1110                                         newCand->expr.get(), &ast::Expr::result, 
     1139                                newCand->expr = ast::mutate_field(
     1140                                        newCand->expr.get(), &ast::Expr::result,
    11111141                                        renameTyVars( newCand->expr->result ) );
    1112                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     1142                                // add anonymous member interpretations whenever an aggregate value type is seen
    11131143                                // as a name expression
    11141144                                addAnonConversions( newCand );
     
    11201150                        // not sufficient to just pass `variableExpr` here, type might have changed since
    11211151                        // creation
    1122                         addCandidate( 
     1152                        addCandidate(
    11231153                                new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
    11241154                }
     
    11301160                void postvisit( const ast::SizeofExpr * sizeofExpr ) {
    11311161                        if ( sizeofExpr->type ) {
    1132                                 addCandidate( 
    1133                                         new ast::SizeofExpr{ 
    1134                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 
     1162                                addCandidate(
     1163                                        new ast::SizeofExpr{
     1164                                                sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
    11351165                                        tenv );
    11361166                        } else {
     
    11411171                                CandidateList winners = findMinCost( finder.candidates );
    11421172                                if ( winners.size() != 1 ) {
    1143                                         SemanticError( 
     1173                                        SemanticError(
    11441174                                                sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );
    11451175                                }
     
    11541184                void postvisit( const ast::AlignofExpr * alignofExpr ) {
    11551185                        if ( alignofExpr->type ) {
    1156                                 addCandidate( 
    1157                                         new ast::AlignofExpr{ 
    1158                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 
     1186                                addCandidate(
     1187                                        new ast::AlignofExpr{
     1188                                                alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
    11591189                                        tenv );
    11601190                        } else {
     
    11651195                                CandidateList winners = findMinCost( finder.candidates );
    11661196                                if ( winners.size() != 1 ) {
    1167                                         SemanticError( 
     1197                                        SemanticError(
    11681198                                                alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );
    11691199                                }
     
    11721202                                choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    11731203                                choice->cost = Cost::zero;
    1174                                 addCandidate( 
     1204                                addCandidate(
    11751205                                        *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );
    11761206                        }
     
    11851215                        for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {
    11861216                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );
    1187                                 addCandidate( 
     1217                                addCandidate(
    11881218                                        new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );
    11891219                        }
     
    12061236                        finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );
    12071237                        if ( finder2.candidates.empty() ) return;
     1238
     1239                        reason.code = NoMatch;
    12081240
    12091241                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    12181250
    12191251                                        addCandidate(
    1220                                                 new ast::LogicalExpr{ 
     1252                                                new ast::LogicalExpr{
    12211253                                                        logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
    12221254                                                move( env ), move( open ), move( need ), r1->cost + r2->cost );
     
    12401272                        finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );
    12411273                        if ( finder3.candidates.empty() ) return;
     1274
     1275                        reason.code = NoMatch;
    12421276
    12431277                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    12561290                                                ast::AssertionSet have;
    12571291
    1258                                                 // unify true and false results, then infer parameters to produce new 
     1292                                                // unify true and false results, then infer parameters to produce new
    12591293                                                // candidates
    12601294                                                ast::ptr< ast::Type > common;
    1261                                                 if ( 
    1262                                                         unify( 
    1263                                                                 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 
    1264                                                                 common ) 
     1295                                                if (
     1296                                                        unify(
     1297                                                                r2->expr->result, r3->expr->result, env, need, have, open, symtab,
     1298                                                                common )
    12651299                                                ) {
    12661300                                                        // generate typed expression
    1267                                                         ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 
     1301                                                        ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{
    12681302                                                                conditionalExpr->location, r1->expr, r2->expr, r3->expr };
    12691303                                                        newExpr->result = common ? common : r2->expr->result;
    12701304                                                        // convert both options to result type
    12711305                                                        Cost cost = r1->cost + r2->cost + r3->cost;
    1272                                                         newExpr->arg2 = computeExpressionConversionCost( 
     1306                                                        newExpr->arg2 = computeExpressionConversionCost(
    12731307                                                                newExpr->arg2, newExpr->result, symtab, env, cost );
    12741308                                                        newExpr->arg3 = computeExpressionConversionCost(
     
    12871321                        ast::TypeEnvironment env{ tenv };
    12881322                        ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
    1289                        
     1323
    12901324                        CandidateFinder finder2{ symtab, env };
    12911325                        finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
     
    13171351                        finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );
    13181352                        if ( finder2.candidates.empty() ) return;
     1353
     1354                        reason.code = NoMatch;
    13191355
    13201356                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    13301366
    13311367                                        ast::ptr< ast::Type > common;
    1332                                         if ( 
    1333                                                 unify( 
    1334                                                         r1->expr->result, r2->expr->result, env, need, have, open, symtab, 
    1335                                                         common ) 
     1368                                        if (
     1369                                                unify(
     1370                                                        r1->expr->result, r2->expr->result, env, need, have, open, symtab,
     1371                                                        common )
    13361372                                        ) {
    13371373                                                // generate new expression
    1338                                                 ast::RangeExpr * newExpr = 
     1374                                                ast::RangeExpr * newExpr =
    13391375                                                        new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
    13401376                                                newExpr->result = common ? common : r1->expr->result;
    13411377                                                // add candidate
    13421378                                                CandidateRef newCand = std::make_shared<Candidate>(
    1343                                                         newExpr, move( env ), move( open ), move( need ), 
     1379                                                        newExpr, move( env ), move( open ), move( need ),
    13441380                                                        r1->cost + r2->cost );
    13451381                                                inferParameters( newCand, candidates );
     
    13501386
    13511387                void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
    1352                         std::vector< CandidateFinder > subCandidates = 
     1388                        std::vector< CandidateFinder > subCandidates =
    13531389                                selfFinder.findSubExprs( tupleExpr->exprs );
    13541390                        std::vector< CandidateList > possibilities;
     
    13701406
    13711407                                addCandidate(
    1372                                         new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 
     1408                                        new ast::TupleExpr{ tupleExpr->location, move( exprs ) },
    13731409                                        move( env ), move( open ), move( need ), sumCost( subs ) );
    13741410                        }
     
    14121448                                toType = SymTab::validateType( initExpr->location, toType, symtab );
    14131449                                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. 
     1450                                // The call to find must occur inside this loop, otherwise polymorphic return
     1451                                // types are not bound to the initialization type, since return type variables are
     1452                                // only open for the duration of resolving the UntypedExpr.
    14171453                                CandidateFinder finder{ symtab, tenv, toType };
    14181454                                finder.find( initExpr->expr, ResolvMode::withAdjustment() );
    14191455                                for ( CandidateRef & cand : finder.candidates ) {
     1456                                        if(reason.code == NotFound) reason.code = NoMatch;
     1457
    14201458                                        ast::TypeEnvironment env{ cand->env };
    14211459                                        ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;
     
    14261464                                        )
    14271465
    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 
     1466                                        // It is possible that a cast can throw away some values in a multiply-valued
     1467                                        // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of
     1468                                        // the subexpression results that are cast directly. The candidate is invalid
    14311469                                        // if it has fewer results than there are types to cast to.
    14321470                                        int discardedValues = cand->expr->result->size() - toType->size();
     
    14351473                                        // unification run for side-effects
    14361474                                        unify( toType, cand->expr->result, env, need, have, open, symtab );
    1437                                         Cost thisCost = castCost( cand->expr->result, toType, symtab, env );
    1438                                        
     1475                                        Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1476                                                        symtab, env );
     1477
    14391478                                        if ( thisCost != Cost::infinity ) {
    14401479                                                // count one safe conversion for each value that is thrown away
    14411480                                                thisCost.incSafe( discardedValues );
    1442                                                 CandidateRef newCand = std::make_shared<Candidate>( 
    1443                                                         new ast::InitExpr{ 
    1444                                                                 initExpr->location, restructureCast( cand->expr, toType ), 
    1445                                                                 initAlt.designation }, 
     1481                                                CandidateRef newCand = std::make_shared<Candidate>(
     1482                                                        new ast::InitExpr{
     1483                                                                initExpr->location, restructureCast( cand->expr, toType ),
     1484                                                                initAlt.designation },
    14461485                                                        copy( cand->env ), move( open ), move( need ), cand->cost, thisCost );
    14471486                                                inferParameters( newCand, matches );
     
    14691508        };
    14701509
    1471         /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
     1510        // size_t Finder::traceId = Stats::Heap::new_stacktrace_id("Finder");
     1511        /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
    14721512        /// return type. Skips ambiguous candidates.
    14731513        CandidateList pruneCandidates( CandidateList & candidates ) {
     
    14861526                        {
    14871527                                ast::ptr< ast::Type > newType = candidate->expr->result;
     1528                                assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());
    14881529                                candidate->env.apply( newType );
    14891530                                mangleName = Mangle::mangle( newType );
     
    14941535                                if ( candidate->cost < found->second.candidate->cost ) {
    14951536                                        PRINT(
    1496                                                 std::cerr << "cost " << candidate->cost << " beats " 
     1537                                                std::cerr << "cost " << candidate->cost << " beats "
    14971538                                                        << found->second.candidate->cost << std::endl;
    14981539                                        )
     
    15001541                                        found->second = PruneStruct{ candidate };
    15011542                                } 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 
     1543                                        // if one of the candidates contains a deleted identifier, can pick the other,
     1544                                        // since deleted expressions should not be ambiguous if there is another option
    15041545                                        // that is at least as good
    15051546                                        if ( findDeletedExpr( candidate->expr ) ) {
     
    15151556                                } else {
    15161557                                        PRINT(
    1517                                                 std::cerr << "cost " << candidate->cost << " loses to " 
     1558                                                std::cerr << "cost " << candidate->cost << " loses to "
    15181559                                                        << found->second.candidate->cost << std::endl;
    15191560                                        )
     
    15301571
    15311572                        CandidateRef cand = target.second.candidate;
    1532                        
     1573
    15331574                        ast::ptr< ast::Type > newResult = cand->expr->result;
    15341575                        cand->env.applyFree( newResult );
    15351576                        cand->expr = ast::mutate_field(
    15361577                                cand->expr.get(), &ast::Expr::result, move( newResult ) );
    1537                        
     1578
    15381579                        out.emplace_back( cand );
    15391580                }
     
    15491590
    15501591        if ( mode.failFast && candidates.empty() ) {
    1551                 SemanticError( expr, "No reasonable alternatives for expression " );
     1592                switch(finder.core.reason.code) {
     1593                case Finder::NotFound:
     1594                        { SemanticError( expr, "No alternatives for expression " ); break; }
     1595                case Finder::NoMatch:
     1596                        { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; }
     1597                case Finder::ArgsToFew:
     1598                case Finder::ArgsToMany:
     1599                case Finder::RetsToFew:
     1600                case Finder::RetsToMany:
     1601                case Finder::NoReason:
     1602                default:
     1603                        { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); }
     1604                }
    15521605        }
    15531606
     
    15581611                std::vector< std::string > errors;
    15591612                for ( CandidateRef & candidate : candidates ) {
    1560                         satisfyAssertions( candidate, symtab, satisfied, errors );
     1613                        satisfyAssertions( candidate, localSyms, satisfied, errors );
    15611614                }
    15621615
     
    15831636
    15841637                CandidateList pruned = pruneCandidates( candidates );
    1585                
     1638
    15861639                if ( mode.failFast && pruned.empty() ) {
    15871640                        std::ostringstream stream;
     
    16021655                )
    16031656                PRINT(
    1604                         std::cerr << "there are " << candidates.size() << " alternatives after elimination" 
     1657                        std::cerr << "there are " << candidates.size() << " alternatives after elimination"
    16051658                                << std::endl;
    16061659                )
    16071660        }
    16081661
    1609         // adjust types after pruning so that types substituted by pruneAlternatives are correctly 
     1662        // adjust types after pruning so that types substituted by pruneAlternatives are correctly
    16101663        // adjusted
    16111664        if ( mode.adjust ) {
    16121665                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 ) );
     1666                        r->expr = ast::mutate_field(
     1667                                r->expr.get(), &ast::Expr::result,
     1668                                adjustExprType( r->expr->result, r->env, localSyms ) );
    16161669                }
    16171670        }
     
    16251678}
    16261679
    1627 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 
    1628         const std::vector< ast::ptr< ast::Expr > > & xs 
     1680std::vector< CandidateFinder > CandidateFinder::findSubExprs(
     1681        const std::vector< ast::ptr< ast::Expr > > & xs
    16291682) {
    16301683        std::vector< CandidateFinder > out;
    16311684
    16321685        for ( const auto & x : xs ) {
    1633                 out.emplace_back( symtab, env );
     1686                out.emplace_back( localSyms, env );
    16341687                out.back().find( x, ResolvMode::withAdjustment() );
    1635                
     1688
    16361689                PRINT(
    16371690                        std::cerr << "findSubExprs" << std::endl;
  • src/ResolvExpr/CandidateFinder.hpp

    r309d814 r4c925cd  
    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  9:51:00 2019
     13// Update Count     : 2
    1414//
    1515
     
    2828struct CandidateFinder {
    2929        CandidateList candidates;          ///< List of candidate resolutions
    30         const ast::SymbolTable & symtab;   ///< Symbol table to lookup candidates
     30        const ast::SymbolTable & localSyms;   ///< Symbol table to lookup candidates
    3131        const ast::TypeEnvironment & env;  ///< Substitutions performed in this resolution
    3232        ast::ptr< ast::Type > targetType;  ///< Target type for resolution
    3333
    34         CandidateFinder( 
    35                 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
     34        CandidateFinder(
     35                const ast::SymbolTable & syms, const ast::TypeEnvironment & env,
    3636                const ast::Type * tt = nullptr )
    37         : candidates(), symtab( symtab ), env( env ), targetType( tt ) {}
     37        : candidates(), localSyms( syms ), env( env ), targetType( tt ) {}
    3838
    3939        /// Fill candidates with feasible resolutions for `expr`
     
    4949        iterator begin() { return candidates.begin(); }
    5050        const_iterator begin() const { return candidates.begin(); }
    51        
     51
    5252        iterator end() { return candidates.end(); }
    5353        const_iterator end() const { return candidates.end(); }
     
    5555
    5656/// Computes conversion cost between two types
    57 Cost computeConversionCost( 
    58         const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab,
    59         const ast::TypeEnvironment & env );
     57Cost computeConversionCost(
     58        const ast::Type * argType, const ast::Type * paramType, bool argIsLvalue,
     59        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
    6060
    6161} // namespace ResolvExpr
  • src/ResolvExpr/CastCost.cc

    r309d814 r4c925cd  
    1010// Created On       : Sun May 17 06:57:43 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Aug  8 16:12:00 2019
    13 // Update Count     : 8
     12// Last Modified On : Tue Oct  4 15:00:00 2019
     13// Update Count     : 9
    1414//
    1515
     
    142142
    143143                CastCost_new(
    144                         const ast::Type * dst, const ast::SymbolTable & symtab,
     144                        const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab,
    145145                        const ast::TypeEnvironment & env, CostCalculation costFunc )
    146                 : ConversionCost_new( dst, symtab, env, costFunc ) {}
     146                : ConversionCost_new( dst, srcIsLvalue, symtab, env, costFunc ) {}
    147147
    148148                void postvisit( const ast::BasicType * basicType ) {
     
    152152                                cost = Cost::unsafe;
    153153                        } else {
    154                                 cost = conversionCost( basicType, dst, symtab, env );
     154                                cost = conversionCost( basicType, dst, srcIsLvalue, symtab, env );
    155155                        }
    156156                }
     
    183183                }
    184184        };
     185
     186        #warning For overload resolution between the two versions.
     187        int localPtrsCastable(const ast::Type * t1, const ast::Type * t2,
     188                        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) {
     189                return ptrsCastable( t1, t2, symtab, env );
     190        }
     191        Cost localCastCost(
     192                const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
     193                const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
     194        ) { return castCost( src, dst, srcIsLvalue, symtab, env ); }
    185195} // anonymous namespace
    186196
     197
     198
    187199Cost castCost(
    188         const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    189         const ast::TypeEnvironment & env
     200        const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
     201        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
    190202) {
    191203        if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
     
    193205                        // check cast cost against bound type, if present
    194206                        if ( eqvClass->bound ) {
    195                                 return castCost( src, eqvClass->bound, symtab, env );
     207                                return castCost( src, eqvClass->bound, srcIsLvalue, symtab, env );
    196208                        } else {
    197209                                return Cost::infinity;
     
    201213                        auto type = strict_dynamic_cast< const ast::TypeDecl * >( named );
    202214                        if ( type->base ) {
    203                                 return castCost( src, type->base, symtab, env ) + Cost::safe;
     215                                return castCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe;
    204216                        }
    205217                }
     
    224236                #warning cast on ptrsCastable artifact of having two functions, remove when port done
    225237                return convertToReferenceCost(
    226                         src, refType, symtab, env,
    227                         ( int (*)(
    228                                 const ast::Type *, const ast::Type *, const ast::SymbolTable &,
    229                                 const ast::TypeEnvironment & )
    230                         ) ptrsCastable );
     238                        src, refType, srcIsLvalue, symtab, env, localPtrsCastable );
    231239        } else {
    232240                #warning cast on castCost artifact of having two functions, remove when port done
    233                 ast::Pass< CastCost_new > converter{
    234                         dst, symtab, env,
    235                         ( Cost (*)(
    236                                 const ast::Type *, const ast::Type *, const ast::SymbolTable &,
    237                                 const ast::TypeEnvironment & )
    238                         ) castCost };
     241                ast::Pass< CastCost_new > converter(
     242                        dst, srcIsLvalue, symtab, env, localCastCost );
    239243                src->accept( converter );
    240                 return converter.pass.cost;
     244                return converter.core.cost;
    241245        }
    242246}
  • src/ResolvExpr/CommonType.cc

    r309d814 r4c925cd  
    666666                const ast::OpenVarSet & open;
    667667        public:
     668                static size_t traceId;
    668669                ast::ptr< ast::Type > result;
    669670
     
    893894        };
    894895
     896        // size_t CommonType_new::traceId = Stats::Heap::new_stacktrace_id("CommonType_new");
    895897        namespace {
    896898                ast::ptr< ast::Type > handleReference(
     
    939941                        ast::ptr< ast::Type > result;
    940942                        const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >();
    941                         const ast::ReferenceType * ref2 = type1.as< ast::ReferenceType >();
     943                        const ast::ReferenceType * ref2 = type2.as< ast::ReferenceType >();
    942944
    943945                        if ( depth1 > depth2 ) {
     
    966968                ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open };
    967969                type1->accept( visitor );
    968                 ast::ptr< ast::Type > result = visitor.pass.result;
     970                ast::ptr< ast::Type > result = visitor.core.result;
    969971
    970972                // handling for opaque type declarations (?)
  • src/ResolvExpr/ConversionCost.cc

    r309d814 r4c925cd  
    481481        }
    482482
    483 static int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
    484                 const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
    485         return ptrsAssignable( t1, t2, env );
    486 }
    487 
    488 // TODO: This is used for overload resolution. It might be able to be dropped once the old system
    489 // is removed.
    490 static Cost localConversionCost(
    491         const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    492         const ast::TypeEnvironment & env
    493 ) { return conversionCost( src, dst, symtab, env ); }
     483namespace {
     484        # warning For overload resolution between the two versions.
     485        int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
     486                        const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
     487                return ptrsAssignable( t1, t2, env );
     488        }
     489        Cost localConversionCost(
     490                const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
     491                const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
     492        ) { return conversionCost( src, dst, srcIsLvalue, symtab, env ); }
     493}
    494494
    495495Cost conversionCost(
    496         const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    497         const ast::TypeEnvironment & env
     496        const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
     497        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
    498498) {
    499499        if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    500500                if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) {
    501501                        if ( eqv->bound ) {
    502                                 return conversionCost(src, eqv->bound, symtab, env );
     502                                return conversionCost(src, eqv->bound, srcIsLvalue, symtab, env );
    503503                        } else {
    504504                                return Cost::infinity;
     
    508508                        assertf( type, "Unexpected typedef." );
    509509                        if ( type->base ) {
    510                                 return conversionCost( src, type->base, symtab, env ) + Cost::safe;
     510                                return conversionCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe;
    511511                        }
    512512                }
     
    518518        } else if ( const ast::ReferenceType * refType =
    519519                         dynamic_cast< const ast::ReferenceType * >( dst ) ) {
    520                 return convertToReferenceCost( src, refType, symtab, env, localPtrsAssignable );
     520                return convertToReferenceCost( src, refType, srcIsLvalue, symtab, env, localPtrsAssignable );
    521521        } else {
    522                 ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
     522                ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
    523523                src->accept( converter );
    524                 return converter.pass.cost;
    525         }
    526 }
    527 
    528 static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst,
     524                return converter.core.cost;
     525        }
     526}
     527
     528static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
    529529                int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
    530                 NumCostCalculation func ) {
     530                PtrsCalculation func ) {
    531531        if ( 0 < diff ) {
    532532                Cost cost = convertToReferenceCost(
    533                         strict_dynamic_cast< const ast::ReferenceType * >( src )->base,
    534                         dst, (diff - 1), symtab, env, func );
     533                        strict_dynamic_cast< const ast::ReferenceType * >( src )->base, dst,
     534                        srcIsLvalue, (diff - 1), symtab, env, func );
    535535                cost.incReference();
    536536                return cost;
     
    538538                Cost cost = convertToReferenceCost(
    539539                        src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base,
    540                         (diff + 1), symtab, env, func );
     540                        srcIsLvalue, (diff + 1), symtab, env, func );
    541541                cost.incReference();
    542542                return cost;
     
    563563                        }
    564564                } else {
    565                         ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
     565                        ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
    566566                        src->accept( converter );
    567                         return converter.pass.cost;
     567                        return converter.core.cost;
    568568                }
    569569        } else {
     
    572572                assert( dstAsRef );
    573573                if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
    574                         if ( src->is_lvalue() ) {
     574                        if ( srcIsLvalue ) {
    575575                                if ( src->qualifiers == dstAsRef->base->qualifiers ) {
    576576                                        return Cost::reference;
     
    591591
    592592Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst,
    593             const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
    594                 NumCostCalculation func ) {
     593                bool srcIsLvalue, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
     594                PtrsCalculation func ) {
    595595        int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth();
    596         return convertToReferenceCost( src, dst, sdepth - ddepth, symtab, env, func );
     596        return convertToReferenceCost( src, dst, srcIsLvalue, sdepth - ddepth, symtab, env, func );
    597597}
    598598
     
    651651        assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
    652652
    653         cost = costCalc( refType->base, dst, symtab, env );
     653        cost = costCalc( refType->base, dst, srcIsLvalue, symtab, env );
    654654        if ( refType->base->qualifiers == dst->qualifiers ) {
    655655                cost.incReference();
     
    667667void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
    668668        (void)enumInstType;
    669         static const ast::BasicType integer( ast::BasicType::SignedInt );
    670         cost = costCalc( &integer, dst, symtab, env );
     669        static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
     670        cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
    671671        if ( cost < Cost::unsafe ) {
    672672                cost.incSafe();
     
    680680void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) {
    681681        if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) {
    682                 cost = costCalc( eqv->bound, dst, symtab, env );
     682                cost = costCalc( eqv->bound, dst, srcIsLvalue, symtab, env );
    683683        } else if ( const ast::TypeInstType * dstAsInst =
    684684                        dynamic_cast< const ast::TypeInstType * >( dst ) ) {
     
    690690                assertf( type, "Unexpected typedef.");
    691691                if ( type->base ) {
    692                         cost = costCalc( type->base, dst, symtab, env ) + Cost::safe;
     692                        cost = costCalc( type->base, dst, srcIsLvalue, symtab, env ) + Cost::safe;
    693693                }
    694694        }
     
    703703                auto dstEnd = dstAsTuple->types.end();
    704704                while ( srcIt != srcEnd && dstIt != dstEnd ) {
    705                         Cost newCost = costCalc( * srcIt++, * dstIt++, symtab, env );
     705                        Cost newCost = costCalc( * srcIt++, * dstIt++, srcIsLvalue, symtab, env );
    706706                        if ( newCost == Cost::infinity ) {
    707707                                return;
     
    738738                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    739739                }
     740        } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
     741                cost = Cost::zero;
     742                // +1 for zero_t ->, +1 for disambiguation
     743                cost.incSafe( maxIntCost + 2 );
    740744        }
    741745}
     
    755759                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    756760                }
    757         } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
    758                 cost = Cost::zero;
    759                 cost.incSafe( maxIntCost + 2 );
    760         }
    761 }
    762 
     761        }
     762}
     763// size_t ConversionCost_new::traceId = Stats::Heap::new_stacktrace_id("ConversionCost");
    763764
    764765} // namespace ResolvExpr
  • src/ResolvExpr/ConversionCost.h

    r309d814 r4c925cd  
    7272
    7373// Some function pointer types, differ in return type.
    74 using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *,
     74using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *, bool,
    7575        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
    76 using NumCostCalculation = std::function<int(const ast::Type *, const ast::Type *,
     76using PtrsCalculation = std::function<int(const ast::Type *, const ast::Type *,
    7777        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
    7878
     
    8181protected:
    8282        const ast::Type * dst;
     83        bool srcIsLvalue;
    8384        const ast::SymbolTable & symtab;
    8485        const ast::TypeEnvironment & env;
    8586        CostCalculation costCalc;
    8687public:
     88        static size_t traceId;
    8789        Cost cost;
    8890
    89         ConversionCost_new( const ast::Type * dst, const ast::SymbolTable & symtab,
     91        ConversionCost_new( const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab,
    9092                        const ast::TypeEnvironment & env, CostCalculation costCalc ) :
    91                 dst( dst ), symtab( symtab ), env( env ), costCalc( costCalc ), cost( Cost::infinity )
     93                dst( dst ), srcIsLvalue( srcIsLvalue ), symtab( symtab ), env( env ),
     94                costCalc( costCalc ), cost( Cost::infinity )
    9295        {}
    9396
     
    110113
    111114Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,
    112         const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, NumCostCalculation func );
     115        bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env,
     116        PtrsCalculation func );
    113117
    114118} // namespace ResolvExpr
  • src/ResolvExpr/CurrentObject.cc

    r309d814 r4c925cd  
    2121#include <string>                      // for string, operator<<, allocator
    2222
     23#include "AST/Copy.hpp"                // for shallowCopy
    2324#include "AST/Expr.hpp"                // for InitAlternative
    2425#include "AST/GenericSubstitution.hpp" // for genericSubstitution
    2526#include "AST/Init.hpp"                // for Designation
    2627#include "AST/Node.hpp"                // for readonly
     28#include "AST/Print.hpp"                // for readonly
    2729#include "AST/Type.hpp"
    2830#include "Common/Indenter.h"           // for Indenter, operator<<
     
    596598                SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
    597599
    598                 void setPosition( 
    599                         std::deque< ptr< Expr > >::const_iterator begin, 
     600                void setPosition(
     601                        std::deque< ptr< Expr > >::const_iterator begin,
    600602                        std::deque< ptr< Expr > >::const_iterator end
    601603                ) override {
     
    637639                        auto res = eval(expr);
    638640                        if ( ! res.second ) {
    639                                 SemanticError( location, 
     641                                SemanticError( location,
    640642                                        toString("Array designator must be a constant expression: ", expr ) );
    641643                        }
     
    644646
    645647        public:
    646                 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) 
     648                ArrayIterator( const CodeLocation & loc, const ArrayType * at )
    647649                : location( loc ), array( at ), base( at->base ) {
    648650                        PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
     
    655657
    656658                void setPosition( const Expr * expr ) {
    657                         // need to permit integer-constant-expressions, including: integer constants, 
    658                         // enumeration constants, character constants, sizeof expressions, alignof expressions, 
     659                        // need to permit integer-constant-expressions, including: integer constants,
     660                        // enumeration constants, character constants, sizeof expressions, alignof expressions,
    659661                        // cast expressions
    660662                        if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) {
     
    662664                                        index = constExpr->intValue();
    663665                                } catch ( SemanticErrorException & ) {
    664                                         SemanticError( expr, 
     666                                        SemanticError( expr,
    665667                                                "Constant expression of non-integral type in array designator: " );
    666668                                }
    667669                        } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) {
    668670                                setPosition( castExpr->arg );
    669                         } else if ( 
    670                                 dynamic_cast< const SizeofExpr * >( expr ) 
    671                                 || dynamic_cast< const AlignofExpr * >( expr ) 
     671                        } else if (
     672                                dynamic_cast< const SizeofExpr * >( expr )
     673                                || dynamic_cast< const AlignofExpr * >( expr )
    672674                        ) {
    673675                                index = 0;
    674676                        } else {
    675                                 assertf( false, 
     677                                assertf( false,
    676678                                        "bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
    677679                        }
    678680                }
    679681
    680                 void setPosition( 
    681                         std::deque< ptr< Expr > >::const_iterator begin, 
     682                void setPosition(
     683                        std::deque< ptr< Expr > >::const_iterator begin,
    682684                        std::deque< ptr< Expr > >::const_iterator end
    683685                ) override {
     
    758760                }
    759761
    760                 AggregateIterator( 
    761                         const CodeLocation & loc, const std::string k, const std::string & n, const Type * i, 
     762                AggregateIterator(
     763                        const CodeLocation & loc, const std::string k, const std::string & n, const Type * i,
    762764                        const MemberList & ms )
    763                 : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ), 
     765                : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ),
    764766                  sub( genericSubstitution( i ) ) {
    765767                        PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
     
    768770
    769771        public:
    770                 void setPosition( 
    771                         std::deque< ptr< Expr > >::const_iterator begin, 
     772                void setPosition(
     773                        std::deque< ptr< Expr > >::const_iterator begin,
    772774                        std::deque< ptr< Expr > >::const_iterator end
    773775                ) final {
     
    786788                                        return;
    787789                                }
    788                                 assertf( false, 
     790                                assertf( false,
    789791                                        "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
    790792                        } else {
    791                                 assertf( false, 
     793                                assertf( false,
    792794                                        "bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() );
    793795                        }
     
    803805                                                new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
    804806                                        // need to substitute for generic types so that casts are to concrete types
     807                                        alt.type = shallowCopy(alt.type.get());
    805808                                        PRINT( std::cerr << "  type is: " << alt.type; )
    806809                                        sub.apply( alt.type ); // also apply to designation??
     
    842845                                for ( InitAlternative & alt : ret ) {
    843846                                        PRINT( std::cerr << "iterating and adding designators" << std::endl; )
    844                                         alt.designation.get_and_mutate()->designators.emplace_front( 
     847                                        alt.designation.get_and_mutate()->designators.emplace_front(
    845848                                                new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
    846849                                }
     
    897900        class TupleIterator final : public AggregateIterator {
    898901        public:
    899                 TupleIterator( const CodeLocation & loc, const TupleType * inst ) 
    900                 : AggregateIterator( 
    901                         loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members 
     902                TupleIterator( const CodeLocation & loc, const TupleType * inst )
     903                : AggregateIterator(
     904                        loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members
    902905                ) {}
    903906
     
    926929                                return new UnionIterator{ loc, uit };
    927930                        } else {
    928                                 assertf( 
    929                                         dynamic_cast< const EnumInstType * >( aggr )
    930                                                 || dynamic_cast< const TypeInstType * >( aggr ),
     931                                assertf(
     932                                        dynamic_cast< const EnumInstType * >( type )
     933                                                || dynamic_cast< const TypeInstType * >( type ),
    931934                                        "Encountered unhandled ReferenceToType in createMemberIterator: %s",
    932935                                                toString( type ).c_str() );
     
    949952                using DesignatorChain = std::deque< ptr< Expr > >;
    950953                PRINT( std::cerr << "___findNext" << std::endl; )
    951                
     954
    952955                // find all the d's
    953956                std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts;
     
    10131016                // set new designators
    10141017                assertf( ! objStack.empty(), "empty object stack when setting designation" );
    1015                 Designation * actualDesignation = 
     1018                Designation * actualDesignation =
    10161019                        new Designation{ designation->location, DesignatorChain{d} };
    10171020                objStack.back()->setPosition( d ); // destroys d
  • src/ResolvExpr/PolyCost.cc

    r309d814 r4c925cd  
    5858
    5959// TODO: When the old PolyCost is torn out get rid of the _new suffix.
    60 struct PolyCost_new {
     60class PolyCost_new {
     61        const ast::SymbolTable &symtab;
     62public:
    6163        int result;
    62         const ast::SymbolTable &symtab;
    6364        const ast::TypeEnvironment &env_;
    6465
    65         PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) :
    66                 result( 0 ), symtab( symtab ), env_( env ) {}
     66        PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env )
     67        : symtab( symtab ), result( 0 ), env_( env ) {}
    6768
    6869        void previsit( const ast::TypeInstType * type ) {
     
    8687        ast::Pass<PolyCost_new> costing( symtab, env );
    8788        type->accept( costing );
    88         return costing.pass.result;
     89        return costing.core.result;
    8990}
    9091
  • src/ResolvExpr/PtrsAssignable.cc

    r309d814 r4c925cd  
    155155                ast::Pass<PtrsAssignable_new> visitor( dst, env );
    156156                src->accept( visitor );
    157                 return visitor.pass.result;
     157                return visitor.core.result;
    158158        }
    159159
  • src/ResolvExpr/PtrsCastable.cc

    r309d814 r4c925cd  
    293293                ast::Pass< PtrsCastable_new > ptrs{ dst, env, symtab };
    294294                src->accept( ptrs );
    295                 return ptrs.pass.result;
     295                return ptrs.core.result;
    296296        }
    297297}
  • src/ResolvExpr/RenameVars.cc

    r309d814 r4c925cd  
    1919#include <utility>                 // for pair
    2020
     21#include "AST/ForallSubstitutionTable.hpp"
    2122#include "AST/Pass.hpp"
    2223#include "AST/Type.hpp"
     
    3031#include "SynTree/Visitor.h"       // for acceptAll, maybeAccept
    3132
     33#include "AST/Copy.hpp"
     34
    3235namespace ResolvExpr {
    3336
     
    3740                int resetCount = 0;
    3841                ScopedMap< std::string, std::string > nameMap;
     42        public:
     43                ast::ForallSubstitutionTable subs;
    3944
    40         public:
    4145                void reset() {
    4246                        level = 0;
     
    4448                }
    4549
    46                 using mapConstIterator = ScopedMap< std::string, std::string >::const_iterator;
    47 
    4850                void rename( TypeInstType * type ) {
    49                         mapConstIterator it = nameMap.find( type->name );
     51                        auto it = nameMap.find( type->name );
    5052                        if ( it != nameMap.end() ) {
    5153                                type->name = it->second;
     
    6567                                        // ditto for assertion names, the next level in
    6668                                        level++;
    67                                         // acceptAll( td->assertions, *this );
    68                                 } // for
    69                         } // if
     69                                }
     70                        }
    7071                }
    7172
     
    7778
    7879                const ast::TypeInstType * rename( const ast::TypeInstType * type ) {
    79                         mapConstIterator it = nameMap.find( type->name );
     80                        // re-linking of base type handled by WithForallSubstitutor
     81
     82                        // rename
     83                        auto it = nameMap.find( type->name );
    8084                        if ( it != nameMap.end() ) {
    81                                 ast::TypeInstType * mutType = ast::mutate( type );
    82                                 mutType->name = it->second;
    83                     type = mutType;
     85                                // unconditionally mutate because map will *always* have different name,
     86                                // if this mutates, will *always* have been mutated by ForallSubstitutor above
     87                                ast::TypeInstType * mut = ast::mutate( type );
     88                                mut->name = it->second;
     89                    type = mut;
    8490                        }
     91
    8592                        return type;
    8693                }
     
    8895                template<typename NodeT>
    8996                const NodeT * openLevel( const NodeT * type ) {
    90                         if ( !type->forall.empty() ) {
    91                                 nameMap.beginScope();
    92                                 // Load new names from this forall clause and perform renaming.
    93                                 NodeT * mutType = ast::mutate( type );
    94                                 for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) {
    95                                         std::ostringstream output;
    96                                         output << "_" << resetCount << "_" << level << "_" << td->name;
    97                                         std::string newname( output.str() );
    98                                         nameMap[ td->name ] = newname;
    99                                         ++level;
     97                        if ( type->forall.empty() ) return type;
    10098
    101                                         ast::TypeDecl * decl = ast::mutate( td.get() );
    102                                         decl->name = newname;
    103                                         td = decl;
    104                                 }
     99                        nameMap.beginScope();
     100
     101                        // Load new names from this forall clause and perform renaming.
     102                        NodeT * mutType = ast::mutate( type );
     103                        assert( type == mutType && "mutated type must be unique from ForallSubstitutor" );
     104                        for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) {
     105                                std::ostringstream output;
     106                                output << "_" << resetCount << "_" << level << "_" << td->name;
     107                                std::string newname =  output.str();
     108                                nameMap[ td->name ] = newname;
     109                                ++level;
     110
     111                                ast::TypeDecl * mutDecl = ast::mutate( td.get() );
     112                                assert( td == mutDecl && "mutated decl must be unique from ForallSubstitutor" );
     113                                mutDecl->name = newname;
     114                                // assertion above means `td = mutDecl;` is unnecessary
    105115                        }
     116                        // assertion above means `type = mutType;` is unnecessary
     117
    106118                        return type;
    107119                }
    108120
    109                 template<typename NodeT>
    110                 const NodeT * closeLevel( const NodeT * type ) {
    111                         if ( !type->forall.empty() ) {
    112                                 nameMap.endScope();
    113                         }
    114                         return type;
     121                void closeLevel( const ast::ParameterizedType * type ) {
     122                        if ( type->forall.empty() ) return;
     123
     124                        nameMap.endScope();
    115125                }
    116126        };
     
    119129        RenamingData renaming;
    120130
    121         struct RenameVars {
     131        struct RenameVars_old {
    122132                void previsit( TypeInstType * instType ) {
    123133                        renaming.openLevel( (Type*)instType );
     
    130140                        renaming.closeLevel( type );
    131141                }
     142        };
     143
     144        struct RenameVars_new /*: public ast::WithForallSubstitutor*/ {
     145                #warning when old RenameVars goes away, replace hack below with global pass inheriting from WithForallSubstitutor
     146                ast::ForallSubstitutionTable & subs = renaming.subs;
    132147
    133148                const ast::FunctionType * previsit( const ast::FunctionType * type ) {
     
    146161                        return renaming.rename( renaming.openLevel( type ) );
    147162                }
    148                 const ast::ParameterizedType * postvisit( const ast::ParameterizedType * type ) {
    149                         return renaming.closeLevel( type );
     163                void postvisit( const ast::ParameterizedType * type ) {
     164                        renaming.closeLevel( type );
    150165                }
    151166        };
     
    154169
    155170void renameTyVars( Type * t ) {
    156         PassVisitor<RenameVars> renamer;
     171        PassVisitor<RenameVars_old> renamer;
    157172        t->accept( renamer );
    158173}
    159174
    160175const ast::Type * renameTyVars( const ast::Type * t ) {
    161         ast::Pass<RenameVars> renamer;
    162         return t->accept( renamer );
     176        ast::Type *tc = ast::deepCopy(t);
     177        ast::Pass<RenameVars_new> renamer;
     178//      return t->accept( renamer );
     179        return tc->accept( renamer );
    163180}
    164181
  • src/ResolvExpr/ResolveTypeof.cc

    r309d814 r4c925cd  
    9999                        // replace basetypeof(<enum>) by int
    100100                        if ( dynamic_cast<EnumInstType*>(newType) ) {
    101                                 Type* newerType = 
    102                                         new BasicType{ newType->get_qualifiers(), BasicType::SignedInt, 
     101                                Type* newerType =
     102                                        new BasicType{ newType->get_qualifiers(), BasicType::SignedInt,
    103103                                        newType->attributes };
    104104                                delete newType;
    105105                                newType = newerType;
    106106                        }
    107                         newType->get_qualifiers().val 
     107                        newType->get_qualifiers().val
    108108                                = ( newType->get_qualifiers().val & ~Type::Qualifiers::Mask ) | oldQuals;
    109109                } else {
    110110                        newType->get_qualifiers().val |= oldQuals;
    111111                }
    112                
     112
    113113                return newType;
    114114        }
     
    120120                ResolveTypeof_new( const ast::SymbolTable & syms ) : localSymtab( syms ) {}
    121121
    122                 void premutate( const ast::TypeofType * ) { visit_children = false; }
     122                void previsit( const ast::TypeofType * ) { visit_children = false; }
    123123
    124                 const ast::Type * postmutate( const ast::TypeofType * typeofType ) {
     124                const ast::Type * postvisit( const ast::TypeofType * typeofType ) {
    125125                        // pass on null expression
    126126                        if ( ! typeofType->expr ) return typeofType;
     
    133133                                // typeof wrapping expression
    134134                                ast::TypeEnvironment dummy;
    135                                 ast::ptr< ast::Expr > newExpr = 
     135                                ast::ptr< ast::Expr > newExpr =
    136136                                        resolveInVoidContext( typeofType->expr, localSymtab, dummy );
    137137                                assert( newExpr->result && ! newExpr->result->isVoid() );
     
    143143                                // replace basetypeof(<enum>) by int
    144144                                if ( newType.as< ast::EnumInstType >() ) {
    145                                         newType = new ast::BasicType{ 
     145                                        newType = new ast::BasicType{
    146146                                                ast::BasicType::SignedInt, newType->qualifiers, copy(newType->attributes) };
    147147                                }
    148                                 reset_qualifiers( 
    149                                         newType, 
     148                                reset_qualifiers(
     149                                        newType,
    150150                                        ( newType->qualifiers & ~ast::CV::EquivQualifiers ) | typeofType->qualifiers );
    151151                        } else {
     
    153153                        }
    154154
    155                         return newType;
     155                        return newType.release();
    156156                }
    157157        };
  • src/ResolvExpr/Resolver.cc

    r309d814 r4c925cd  
    982982                ast::Pass<DeleteFinder_new> finder;
    983983                expr->accept( finder );
    984                 return finder.pass.delExpr;
     984                return finder.core.delExpr;
    985985        }
    986986
     
    10721072                /// Strips extraneous casts out of an expression
    10731073                struct StripCasts_new final {
    1074                         const ast::Expr * postmutate( const ast::CastExpr * castExpr ) {
     1074                        const ast::Expr * postvisit( const ast::CastExpr * castExpr ) {
    10751075                                if (
    1076                                         castExpr->isGenerated
     1076                                        castExpr->isGenerated == ast::GeneratedCast
    10771077                                        && typesCompatible( castExpr->arg->result, castExpr->result )
    10781078                                ) {
     
    11281128
    11291129                // set up and resolve expression cast to void
    1130                 ast::CastExpr * untyped = new ast::CastExpr{ expr };
     1130                ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
    11311131                CandidateRef choice = findUnfinishedKindExpression(
    11321132                        untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
     
    12361236
    12371237        public:
     1238                static size_t traceId;
    12381239                Resolver_new() = default;
    12391240                Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
     
    12661267                const ast::ConstructorInit * previsit( const ast::ConstructorInit * );
    12671268        };
    1268 
    1269         void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) {
    1270                 ast::Pass< Resolver_new > resolver;
    1271                 accept_all( translationUnit, resolver );
     1269        // size_t Resolver_new::traceId = Stats::Heap::new_stacktrace_id("Resolver");
     1270
     1271        void resolve( std::list< ast::ptr< ast::Decl > >& translationUnit ) {
     1272                ast::Pass< Resolver_new >::run( translationUnit );
    12721273        }
    12731274
     
    12991300                // default value expressions have an environment which shouldn't be there and trips up
    13001301                // later passes.
    1301                 ast::ptr< ast::FunctionDecl > ret = functionDecl;
    1302                 for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {
    1303                         const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i];
    1304 
    1305                         if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {
     1302                assert( functionDecl->unique() );
     1303                ast::FunctionType * mutType = mutate( functionDecl->type.get() );
     1304
     1305                for ( unsigned i = 0 ; i < mutType->params.size() ; ++i ) {
     1306                        if ( const ast::ObjectDecl * obj = mutType->params[i].as< ast::ObjectDecl >() ) {
    13061307                                if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) {
    13071308                                        if ( init->value->env == nullptr ) continue;
    13081309                                        // clone initializer minus the initializer environment
    1309                                         ast::chain_mutate( ret )
    1310                                                 ( &ast::FunctionDecl::type )
    1311                                                         ( &ast::FunctionType::params )[i]
    1312                                                                 ( &ast::ObjectDecl::init )
    1313                                                                         ( &ast::SingleInit::value )->env = nullptr;
    1314 
    1315                                         assert( functionDecl != ret.get() || functionDecl->unique() );
    1316                                         assert( ! ret->type->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env );
     1310                                        auto mutParam = mutate( mutType->params[i].strict_as< ast::ObjectDecl >() );
     1311                                        auto mutInit = mutate( mutParam->init.strict_as< ast::SingleInit >() );
     1312                                        auto mutValue = mutate( mutInit->value.get() );
     1313
     1314                                        mutValue->env = nullptr;
     1315                                        mutInit->value = mutValue;
     1316                                        mutParam->init = mutInit;
     1317                                        mutType->params[i] = mutParam;
     1318
     1319                                        assert( ! mutType->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env);
    13171320                                }
    13181321                        }
    13191322                }
    1320                 return ret.get();
     1323                mutate_field(functionDecl, &ast::FunctionDecl::type, mutType);
     1324                return functionDecl;
    13211325        }
    13221326
     
    13411345                // in case we decide to allow nested enums
    13421346                GuardValue( inEnumDecl );
    1343                 inEnumDecl = false;
     1347                inEnumDecl = true;
    13441348        }
    13451349
  • src/ResolvExpr/SatisfyAssertions.cpp

    r309d814 r4c925cd  
    99// Author           : Aaron B. Moss
    1010// Created On       : Mon Jun 10 17:45:00 2019
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Mon Jun 10 17:45:00 2019
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Oct  1 13:56:00 2019
     13// Update Count     : 2
    1414//
    1515
     
    188188
    189189                                matches.emplace_back(
    190                                         cdata, adjType, std::move( newEnv ), std::move( newNeed ), std::move( have ),
     190                                        cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
    191191                                        std::move( newOpen ), crntResnSlot );
    192192                        }
     
    229229                InferMatcher( InferCache & inferred ) : inferred( inferred ) {}
    230230
    231                 const ast::Expr * postmutate( const ast::Expr * expr ) {
     231                const ast::Expr * postvisit( const ast::Expr * expr ) {
    232232                        // Skip if no slots to find
    233                         if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr;
    234 
     233                        if ( !expr->inferred.hasSlots() ) return expr;
     234                        // if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr;
     235                        std::vector<UniqueId> missingSlots;
    235236                        // find inferred parameters for resolution slots
    236                         ast::InferredParams newInferred;
     237                        ast::InferredParams * newInferred = new ast::InferredParams();
    237238                        for ( UniqueId slot : expr->inferred.resnSlots() ) {
    238239                                // fail if no matching assertions found
    239240                                auto it = inferred.find( slot );
    240241                                if ( it == inferred.end() ) {
    241                                         assert(!"missing assertion");
     242                                        std::cerr << "missing assertion " << slot << std::endl;
     243                                        missingSlots.push_back(slot);
     244                                        continue;
    242245                                }
    243246
     
    245248                                for ( auto & entry : it->second ) {
    246249                                        // recurse on inferParams of resolved expressions
    247                                         entry.second.expr = postmutate( entry.second.expr );
    248                                         auto res = newInferred.emplace( entry );
     250                                        entry.second.expr = postvisit( entry.second.expr );
     251                                        auto res = newInferred->emplace( entry );
    249252                                        assert( res.second && "all assertions newly placed" );
    250253                                }
     
    252255
    253256                        ast::Expr * ret = mutate( expr );
    254                         ret->inferred.set_inferParams( std::move( newInferred ) );
     257                        ret->inferred.set_inferParams( newInferred );
     258                        if (!missingSlots.empty()) ret->inferred.resnSlots() = missingSlots;
    255259                        return ret;
    256260                }
     
    299303                        Cost cost;
    300304
    301                         OutType( 
    302                                 const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 
     305                        OutType(
     306                                const ast::TypeEnvironment & e, const ast::OpenVarSet & o,
    303307                                const std::vector< DeferRef > & as, const ast::SymbolTable & symtab )
    304308                        : env( e ), open( o ), assns( as ), cost( Cost::zero ) {
     
    306310                                for ( const DeferRef & assn : assns ) {
    307311                                        // compute conversion cost from satisfying decl to assertion
    308                                         cost += computeConversionCost( 
    309                                                 assn.match.adjType, assn.decl->get_type(), symtab, env );
    310                                        
     312                                        cost += computeConversionCost(
     313                                                assn.match.adjType, assn.decl->get_type(), false, symtab, env );
     314
    311315                                        // mark vars+specialization on function-type assertions
    312                                         const ast::FunctionType * func = 
     316                                        const ast::FunctionType * func =
    313317                                                GenPoly::getFunctionType( assn.match.cdata.id->get_type() );
    314318                                        if ( ! func ) continue;
     
    317321                                                cost.decSpec( specCost( param->get_type() ) );
    318322                                        }
    319                                        
     323
    320324                                        cost.incVar( func->forall.size() );
    321                                        
     325
    322326                                        for ( const ast::TypeDecl * td : func->forall ) {
    323327                                                cost.decSpec( td->assertions.size() );
     
    329333                };
    330334
    331                 CandidateEnvMerger( 
    332                         const ast::TypeEnvironment & env, const ast::OpenVarSet & open, 
     335                CandidateEnvMerger(
     336                        const ast::TypeEnvironment & env, const ast::OpenVarSet & open,
    333337                        const ast::SymbolTable & syms )
    334338                : crnt(), envs{ env }, opens{ open }, symtab( syms ) {}
  • src/ResolvExpr/SatisfyAssertions.hpp

    r309d814 r4c925cd  
    2828
    2929/// Recursively satisfies all assertions provided in a candidate; returns true if succeeds
    30 void satisfyAssertions( 
    31         CandidateRef & cand, const ast::SymbolTable & symtab, CandidateList & out, 
     30void satisfyAssertions(
     31        CandidateRef & cand, const ast::SymbolTable & symtab, CandidateList & out,
    3232        std::vector<std::string> & errors );
    3333
  • src/ResolvExpr/SpecCost.cc

    r309d814 r4c925cd  
    1010// Created On       : Tue Oct 02 15:50:00 2018
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jun 19 10:43:00 2019
    13 // Update Count     : 2
    14 //
    15 
     12// Last Modified On : Wed Jul  3 11:07:00 2019
     13// Update Count     : 3
     14//
     15
     16#include <cassert>
    1617#include <limits>
    1718#include <list>
     
    129130                        typename std::add_pointer<ast::Type const *(typename T::value_type const &)>::type;
    130131
     132                #warning Should use a standard maybe_accept
     133                void maybe_accept( ast::Type const * type ) {
     134                        if ( type ) {
     135                                auto node = type->accept( *visitor );
     136                                assert( node == nullptr || node == type );
     137                        }
     138                }
     139
    131140                // Update the minimum to the new lowest non-none value.
    132141                template<typename T>
     
    134143                        for ( const auto & node : list ) {
    135144                                count = -1;
    136                                 mapper( node )->accept( *visitor );
     145                                maybe_accept( mapper( node ) );
    137146                                if ( count != -1 && count < minimum ) minimum = count;
    138147                        }
     
    208217        }
    209218        ast::Pass<SpecCounter> counter;
    210         type->accept( *counter.pass.visitor );
    211         return counter.pass.get_count();
     219        type->accept( counter );
     220        return counter.core.get_count();
    212221}
    213222
  • src/ResolvExpr/Unify.cc

    r309d814 r4c925cd  
    2525#include <vector>
    2626
     27#include "AST/Copy.hpp"
    2728#include "AST/Decl.hpp"
    2829#include "AST/Node.hpp"
    2930#include "AST/Pass.hpp"
     31#include "AST/Print.hpp"
    3032#include "AST/Type.hpp"
    3133#include "AST/TypeEnvironment.hpp"
     
    135137                findOpenVars( newSecond, open, closed, need, have, FirstOpen );
    136138
    137                 return unifyExact(
    138                         newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     139                return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
    139140        }
    140141
     
    148149                newFirst->get_qualifiers() = Type::Qualifiers();
    149150                newSecond->get_qualifiers() = Type::Qualifiers();
    150 ///   std::cerr << "first is ";
    151 ///   first->print( std::cerr );
    152 ///   std::cerr << std::endl << "second is ";
    153 ///   second->print( std::cerr );
    154 ///   std::cerr << std::endl << "newFirst is ";
    155 ///   newFirst->print( std::cerr );
    156 ///   std::cerr << std::endl << "newSecond is ";
    157 ///   newSecond->print( std::cerr );
    158 ///   std::cerr << std::endl;
     151
    159152                bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    160153                delete newFirst;
     
    170163                ast::AssertionSet need, have;
    171164
    172                 ast::ptr<ast::Type> newFirst{ first }, newSecond{ second };
    173                 env.apply( newFirst );
    174                 env.apply( newSecond );
    175                 reset_qualifiers( newFirst );
    176                 reset_qualifiers( newSecond );
     165                ast::Type * newFirst  = shallowCopy( first  );
     166                ast::Type * newSecond = shallowCopy( second );
     167                newFirst ->qualifiers = {};
     168                newSecond->qualifiers = {};
     169                ast::ptr< ast::Type > t1_(newFirst );
     170                ast::ptr< ast::Type > t2_(newSecond);
     171
     172                ast::ptr< ast::Type > subFirst = env.apply(newFirst).node;
     173                ast::ptr< ast::Type > subSecond = env.apply(newSecond).node;
    177174
    178175                return unifyExact(
    179                         newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     176                        subFirst,
     177                        subSecond,
     178                        newEnv, need, have, open, noWiden(), symtab );
    180179        }
    181180
     
    326325
    327326        void markAssertionSet( AssertionSet &assertions, DeclarationWithType *assert ) {
    328 ///   std::cerr << "assertion set is" << std::endl;
    329 ///   printAssertionSet( assertions, std::cerr, 8 );
    330 ///   std::cerr << "looking for ";
    331 ///   assert->print( std::cerr );
    332 ///   std::cerr << std::endl;
    333327                AssertionSet::iterator i = assertions.find( assert );
    334328                if ( i != assertions.end() ) {
    335 ///     std::cerr << "found it!" << std::endl;
    336329                        i->second.isUsed = true;
    337330                } // if
     
    709702                const ast::SymbolTable & symtab;
    710703        public:
     704                static size_t traceId;
    711705                bool result;
    712706
     
    943937
    944938        private:
    945                 template< typename RefType >
    946                 const RefType * handleRefType( const RefType * inst, const ast::Type * other ) {
     939                // Returns: other, cast as XInstType
     940                // Assigns this->result: whether types are compatible (up to generic parameters)
     941                template< typename XInstType >
     942                const XInstType * handleRefType( const XInstType * inst, const ast::Type * other ) {
    947943                        // check that the other type is compatible and named the same
    948                         auto otherInst = dynamic_cast< const RefType * >( other );
    949                         result = otherInst && inst->name == otherInst->name;
     944                        auto otherInst = dynamic_cast< const XInstType * >( other );
     945                        this->result = otherInst && inst->name == otherInst->name;
    950946                        return otherInst;
    951947                }
     
    968964                }
    969965
    970                 template< typename RefType >
    971                 void handleGenericRefType( const RefType * inst, const ast::Type * other ) {
     966                template< typename XInstType >
     967                void handleGenericRefType( const XInstType * inst, const ast::Type * other ) {
    972968                        // check that other type is compatible and named the same
    973                         const RefType * inst2 = handleRefType( inst, other );
    974                         if ( ! inst2 ) return;
     969                        const XInstType * otherInst = handleRefType( inst, other );
     970                        if ( ! this->result ) return;
    975971
    976972                        // check that parameters of types unify, if any
    977973                        const std::vector< ast::ptr< ast::Expr > > & params = inst->params;
    978                         const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params;
     974                        const std::vector< ast::ptr< ast::Expr > > & params2 = otherInst->params;
    979975
    980976                        auto it = params.begin();
     
    11401136        };
    11411137
     1138        // size_t Unify_new::traceId = Stats::Heap::new_stacktrace_id("Unify_new");
    11421139        bool unify(
    11431140                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     
    11881185                        ast::Pass<Unify_new> comparator{ type2, env, need, have, open, widen, symtab };
    11891186                        type1->accept( comparator );
    1190                         return comparator.pass.result;
     1187                        return comparator.core.result;
    11911188                }
    11921189        }
     
    12021199                // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and
    12031200                // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1
    1204                 ast::ptr<ast::Type> t1{ type1 }, t2{ type2 };
    1205                 reset_qualifiers( t1 );
    1206                 reset_qualifiers( t2 );
     1201                ast::Type * t1 = shallowCopy(type1.get());
     1202                ast::Type * t2 = shallowCopy(type2.get());
     1203                t1->qualifiers = {};
     1204                t2->qualifiers = {};
     1205                ast::ptr< ast::Type > t1_(t1);
     1206                ast::ptr< ast::Type > t2_(t2);
    12071207
    12081208                if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
    1209                         t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
    1210 
    12111209                        // if exact unification on unqualified types, try to merge qualifiers
    12121210                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
    1213                                 common = type1;
    1214                                 reset_qualifiers( common, q1 | q2 );
     1211                                t1->qualifiers = q1 | q2;
     1212                                common = t1;
    12151213                                return true;
    12161214                        } else {
     
    12191217
    12201218                } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {
    1221                         t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
    1222 
    12231219                        // no exact unification, but common type
    1224                         reset_qualifiers( common, q1 | q2 );
     1220                        auto c = shallowCopy(common.get());
     1221                        c->qualifiers = q1 | q2;
     1222                        common = c;
    12251223                        return true;
    12261224                } else {
  • src/ResolvExpr/typeops.h

    r309d814 r4c925cd  
    1010// Created On       : Sun May 17 07:28:22 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Aug  8 16:36:00 2019
    13 // Update Count     : 5
     12// Last Modified On : Tue Oct  1 09:45:00 2019
     13// Update Count     : 6
    1414//
    1515
     
    8383                const SymTab::Indexer & indexer, const TypeEnvironment & env );
    8484        Cost castCost(
    85                 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    86                 const ast::TypeEnvironment & env );
     85                const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
     86                const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
    8787
    8888        // in ConversionCost.cc
     
    9090                const SymTab::Indexer & indexer, const TypeEnvironment & env );
    9191        Cost conversionCost(
    92                 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    93                 const ast::TypeEnvironment & env );
     92                const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
     93                const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
    9494
    9595        // in AlternativeFinder.cc
Note: See TracChangeset for help on using the changeset viewer.