Changeset eef8dfb for src/ResolvExpr


Ignore:
Timestamp:
Jan 7, 2021, 2:55:57 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
58fe85a
Parents:
bdfc032 (diff), 44e37ef (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into dkobets-vector

Location:
src/ResolvExpr
Files:
31 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AdjustExprType.cc

    rbdfc032 reef8dfb  
    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
    134                         if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name ) ) {
     135                        if ( const ast::EqvClass * eqvClass = tenv.lookup( *inst ) ) {
    135136                                if ( eqvClass->data.kind == ast::TypeDecl::Ftype ) {
    136137                                        return new ast::PointerType{ inst };
  • src/ResolvExpr/AlternativeFinder.cc

    rbdfc032 reef8dfb  
    131131
    132132        void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt ) {
    133                 Indenter indent = { indentAmt };
    134                 for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
    135                         i->print( os, indent );
    136                         os << std::endl;
     133                std::vector<std::string> sorted;
     134                sorted.reserve(list.size());
     135                for(const auto & c : list) {
     136                        std::stringstream ss;
     137                        c.print( ss, indentAmt );
     138                        sorted.push_back(ss.str());
     139                }
     140
     141                std::sort(sorted.begin(), sorted.end());
     142
     143                for ( const auto & s : sorted ) {
     144                        os << s << std::endl;
    137145                }
    138146        }
     
    251259                        SemanticError( expr, "No reasonable alternatives for expression " );
    252260                }
    253                 if ( mode.satisfyAssns || mode.prune ) {
     261                if ( mode.prune ) {
    254262                        // trim candidates just to those where the assertions resolve
    255263                        // - necessary pre-requisite to pruning
     
    12161224                        unify( castExpr->result, alt.expr->result, alt.env, needAssertions,
    12171225                                haveAssertions, openVars, indexer );
    1218                         Cost thisCost = castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(),
    1219                                 indexer, alt.env );
     1226                        Cost thisCost =
     1227                                castExpr->isGenerated
     1228                                ? conversionCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(),   indexer, alt.env )
     1229                                : castCost( alt.expr->result, castExpr->result, alt.expr->get_lvalue(), indexer, alt.env );
    12201230                        PRINT(
    12211231                                std::cerr << "working on cast with result: " << castExpr->result << std::endl;
     
    12921302
    12931303                try {
    1294                         // Attempt 1 : turn (thread&)X into (thread_desc&)X.__thrd
     1304                        // Attempt 1 : turn (thread&)X into ($thread&)X.__thrd
    12951305                        // Clone is purely for memory management
    12961306                        std::unique_ptr<Expression> tech1 { new UntypedMemberExpr(new NameExpr(castExpr->concrete_target.field), castExpr->arg->clone()) };
     
    13031313                } catch(SemanticErrorException & ) {}
    13041314
    1305                 // Fallback : turn (thread&)X into (thread_desc&)get_thread(X)
     1315                // Fallback : turn (thread&)X into ($thread&)get_thread(X)
    13061316                std::unique_ptr<Expression> fallback { UntypedExpr::createDeref( new UntypedExpr(new NameExpr(castExpr->concrete_target.getter), { castExpr->arg->clone() })) };
    13071317                // don't prune here, since it's guaranteed all alternatives will have the same type
     
    16981708
    16991709                                // unification run for side-effects
    1700                                 unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer );
     1710                                bool canUnify = unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer );
     1711                                (void) canUnify;
    17011712                                // xxx - do some inspecting on this line... why isn't result bound to initAlt.type?
    17021713
    1703                                 Cost thisCost = castCost( alt.expr->result, toType, alt.expr->get_lvalue(),
     1714                                Cost thisCost = computeConversionCost( alt.expr->result, toType, alt.expr->get_lvalue(),
    17041715                                        indexer, newEnv );
     1716
     1717                                PRINT(
     1718                                        Cost legacyCost = castCost( alt.expr->result, toType, alt.expr->get_lvalue(),
     1719                                                indexer, newEnv );
     1720                                        std::cerr << "Considering initialization:";
     1721                                        std::cerr << std::endl << "  FROM: "; alt.expr->result->print(std::cerr);
     1722                                        std::cerr << std::endl << "  TO: ";   toType          ->print(std::cerr);
     1723                                        std::cerr << std::endl << "  Unification " << (canUnify ? "succeeded" : "failed");
     1724                                        std::cerr << std::endl << "  Legacy cost " << legacyCost;
     1725                                        std::cerr << std::endl << "  New cost " << thisCost;
     1726                                        std::cerr << std::endl;
     1727                                )
     1728
    17051729                                if ( thisCost != Cost::infinity ) {
    17061730                                        // count one safe conversion for each value that is thrown away
  • src/ResolvExpr/Candidate.cpp

    rbdfc032 reef8dfb  
    4141
    4242void print( std::ostream & os, const CandidateList & cands, Indenter indent ) {
    43         for ( const CandidateRef & cand : cands ) {
    44                 print( os, *cand, indent );
    45                 os << std::endl;
     43        std::vector<std::string> sorted;
     44        sorted.reserve(cands.size());
     45        for(const auto & c : cands) {
     46                std::stringstream ss;
     47                print( ss, *c, indent );
     48                sorted.push_back(ss.str());
     49        }
     50
     51        std::sort(sorted.begin(), sorted.end());
     52
     53        for ( const auto & s : sorted ) {
     54                os << s << std::endl;
    4655        }
    4756}
  • src/ResolvExpr/Candidate.hpp

    rbdfc032 reef8dfb  
    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

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

    rbdfc032 reef8dfb  
    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
     33        std::set< std::string > otypeKeys;  /// different type may map to same key
    3334
    34         CandidateFinder( 
    35                 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
     35        CandidateFinder(
     36                const ast::SymbolTable & syms, const ast::TypeEnvironment & env,
    3637                const ast::Type * tt = nullptr )
    37         : candidates(), symtab( symtab ), env( env ), targetType( tt ) {}
     38        : candidates(), localSyms( syms ), env( env ), targetType( tt ) {}
    3839
    3940        /// Fill candidates with feasible resolutions for `expr`
    4041        void find( const ast::Expr * expr, ResolvMode mode = {} );
     42        bool pruneCandidates( CandidateList & candidates, CandidateList & out, std::vector<std::string> & errors );
    4143
    4244        /// Runs new candidate finder on each element in xs, returning the list of finders
     
    4951        iterator begin() { return candidates.begin(); }
    5052        const_iterator begin() const { return candidates.begin(); }
    51        
     53
    5254        iterator end() { return candidates.end(); }
    5355        const_iterator end() const { return candidates.end(); }
     
    5557
    5658/// 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 );
     59Cost computeConversionCost(
     60        const ast::Type * argType, const ast::Type * paramType, bool argIsLvalue,
     61        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
    6062
    6163} // namespace ResolvExpr
  • src/ResolvExpr/CastCost.cc

    rbdfc032 reef8dfb  
    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                }
     
    165165                                } else {
    166166                                        ast::TypeEnvironment newEnv{ env };
    167                                         if ( auto wParams = pointerType->base.as< ast::ParameterizedType >() ) {
     167                                        if ( auto wParams = pointerType->base.as< ast::FunctionType >() ) {
    168168                                                newEnv.add( wParams->forall );
    169169                                        }
     
    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 ) ) {
    192                 if ( const ast::EqvClass * eqvClass = env.lookup( typeInst->name ) ) {
     204                if ( const ast::EqvClass * eqvClass = env.lookup( *typeInst ) ) {
    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

    rbdfc032 reef8dfb  
    666666                const ast::OpenVarSet & open;
    667667        public:
     668                static size_t traceId;
    668669                ast::ptr< ast::Type > result;
    669670
     
    712713                        const ast::Type * base = oPtr->base;
    713714                        if ( auto var = dynamic_cast< const ast::TypeInstType * >( base ) ) {
    714                                 auto entry = open.find( var->name );
     715                                auto entry = open.find( *var );
    715716                                if ( entry != open.end() ) {
    716717                                        ast::AssertionSet need, have;
     
    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

    rbdfc032 reef8dfb  
    1010// Created On       : Sun May 17 07:06:19 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Aug 12 10:21:00 2019
    13 // Update Count     : 27
     12// Last Modified On : Wed Jul 29 16:11:00 2020
     13// Update Count     : 28
    1414//
    1515
     
    392392        void ConversionCost::postvisit( const FunctionType * ) {}
    393393
    394         void ConversionCost::postvisit( const StructInstType * inst ) {
    395                 if ( const StructInstType * destAsInst = dynamic_cast< const StructInstType * >( dest ) ) {
    396                         if ( inst->name == destAsInst->name ) {
    397                                 cost = Cost::zero;
    398                         } // if
    399                 } // if
    400         }
    401 
    402         void ConversionCost::postvisit( const UnionInstType * inst ) {
    403                 if ( const UnionInstType * destAsInst = dynamic_cast< const UnionInstType * >( dest ) ) {
    404                         if ( inst->name == destAsInst->name ) {
    405                                 cost = Cost::zero;
    406                         } // if
    407                 } // if
    408         }
    409 
    410394        void ConversionCost::postvisit( const EnumInstType * ) {
    411395                static Type::Qualifiers q;
     
    497481        }
    498482
    499 static int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
    500                 const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
    501         return ptrsAssignable( t1, t2, env );
    502 }
    503 
    504 // TODO: This is used for overload resolution. It might be able to be dropped once the old system
    505 // is removed.
    506 static Cost localConversionCost(
    507         const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    508         const ast::TypeEnvironment & env
    509 ) { 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}
    510494
    511495Cost conversionCost(
    512         const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    513         const ast::TypeEnvironment & env
     496        const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
     497        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
    514498) {
    515499        if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    516                 if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) {
     500                if ( const ast::EqvClass * eqv = env.lookup( *inst ) ) {
    517501                        if ( eqv->bound ) {
    518                                 return conversionCost(src, eqv->bound, symtab, env );
     502                                return conversionCost(src, eqv->bound, srcIsLvalue, symtab, env );
    519503                        } else {
    520504                                return Cost::infinity;
     
    524508                        assertf( type, "Unexpected typedef." );
    525509                        if ( type->base ) {
    526                                 return conversionCost( src, type->base, symtab, env ) + Cost::safe;
     510                                return conversionCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe;
    527511                        }
    528512                }
     
    534518        } else if ( const ast::ReferenceType * refType =
    535519                         dynamic_cast< const ast::ReferenceType * >( dst ) ) {
    536                 return convertToReferenceCost( src, refType, symtab, env, localPtrsAssignable );
     520                return convertToReferenceCost( src, refType, srcIsLvalue, symtab, env, localPtrsAssignable );
    537521        } else {
    538                 ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
    539                 src->accept( converter );
    540                 return converter.pass.cost;
    541         }
    542 }
    543 
    544 static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst,
     522                return ast::Pass<ConversionCost_new>::read( src, dst, srcIsLvalue, symtab, env, localConversionCost );
     523        }
     524}
     525
     526static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
    545527                int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
    546                 NumCostCalculation func ) {
     528                PtrsCalculation func ) {
    547529        if ( 0 < diff ) {
    548530                Cost cost = convertToReferenceCost(
    549                         strict_dynamic_cast< const ast::ReferenceType * >( src )->base,
    550                         dst, (diff - 1), symtab, env, func );
     531                        strict_dynamic_cast< const ast::ReferenceType * >( src )->base, dst,
     532                        srcIsLvalue, (diff - 1), symtab, env, func );
    551533                cost.incReference();
    552534                return cost;
     
    554536                Cost cost = convertToReferenceCost(
    555537                        src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base,
    556                         (diff + 1), symtab, env, func );
     538                        srcIsLvalue, (diff + 1), symtab, env, func );
    557539                cost.incReference();
    558540                return cost;
     
    579561                        }
    580562                } else {
    581                         ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
    582                         src->accept( converter );
    583                         return converter.pass.cost;
     563                        return ast::Pass<ConversionCost_new>::read( src, dst, srcIsLvalue, symtab, env, localConversionCost );
    584564                }
    585565        } else {
     
    588568                assert( dstAsRef );
    589569                if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
    590                         if ( src->is_lvalue() ) {
     570                        if ( srcIsLvalue ) {
    591571                                if ( src->qualifiers == dstAsRef->base->qualifiers ) {
    592572                                        return Cost::reference;
     
    607587
    608588Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst,
    609             const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
    610                 NumCostCalculation func ) {
     589                bool srcIsLvalue, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
     590                PtrsCalculation func ) {
    611591        int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth();
    612         return convertToReferenceCost( src, dst, sdepth - ddepth, symtab, env, func );
     592        return convertToReferenceCost( src, dst, srcIsLvalue, sdepth - ddepth, symtab, env, func );
    613593}
    614594
     
    667647        assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
    668648
    669         cost = costCalc( refType->base, dst, symtab, env );
     649        cost = costCalc( refType->base, dst, srcIsLvalue, symtab, env );
    670650        if ( refType->base->qualifiers == dst->qualifiers ) {
    671651                cost.incReference();
     
    681661}
    682662
    683 void ConversionCost_new::postvisit( const ast::StructInstType * structInstType ) {
    684         if ( const ast::StructInstType * dstAsInst =
    685                         dynamic_cast< const ast::StructInstType * >( dst ) ) {
    686                 if ( structInstType->name == dstAsInst->name ) {
    687                         cost = Cost::zero;
    688                 }
    689         }
    690 }
    691 
    692 void ConversionCost_new::postvisit( const ast::UnionInstType * unionInstType ) {
    693         if ( const ast::UnionInstType * dstAsInst =
    694                         dynamic_cast< const ast::UnionInstType * >( dst ) ) {
    695                 if ( unionInstType->name == dstAsInst->name ) {
    696                         cost = Cost::zero;
    697                 }
    698         }
    699 }
    700 
    701663void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
    702664        (void)enumInstType;
    703         static const ast::BasicType integer( ast::BasicType::SignedInt );
    704         cost = costCalc( &integer, dst, symtab, env );
     665        static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
     666        cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
    705667        if ( cost < Cost::unsafe ) {
    706668                cost.incSafe();
     
    713675
    714676void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) {
    715         if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) {
    716                 cost = costCalc( eqv->bound, dst, symtab, env );
     677        if ( const ast::EqvClass * eqv = env.lookup( *typeInstType ) ) {
     678                cost = costCalc( eqv->bound, dst, srcIsLvalue, symtab, env );
    717679        } else if ( const ast::TypeInstType * dstAsInst =
    718680                        dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    719                 if ( typeInstType->name == dstAsInst->name ) {
     681                if ( *typeInstType == *dstAsInst ) {
    720682                        cost = Cost::zero;
    721683                }
     
    724686                assertf( type, "Unexpected typedef.");
    725687                if ( type->base ) {
    726                         cost = costCalc( type->base, dst, symtab, env ) + Cost::safe;
     688                        cost = costCalc( type->base, dst, srcIsLvalue, symtab, env ) + Cost::safe;
    727689                }
    728690        }
     
    737699                auto dstEnd = dstAsTuple->types.end();
    738700                while ( srcIt != srcEnd && dstIt != dstEnd ) {
    739                         Cost newCost = costCalc( * srcIt++, * dstIt++, symtab, env );
     701                        Cost newCost = costCalc( * srcIt++, * dstIt++, srcIsLvalue, symtab, env );
    740702                        if ( newCost == Cost::infinity ) {
    741703                                return;
     
    772734                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    773735                }
     736        } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
     737                cost = Cost::zero;
     738                // +1 for zero_t ->, +1 for disambiguation
     739                cost.incSafe( maxIntCost + 2 );
    774740        }
    775741}
     
    789755                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    790756                }
    791         } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
    792                 cost = Cost::zero;
    793                 cost.incSafe( maxIntCost + 2 );
    794         }
    795 }
    796 
     757        }
     758}
     759// size_t ConversionCost_new::traceId = Stats::Heap::new_stacktrace_id("ConversionCost");
    797760
    798761} // namespace ResolvExpr
  • src/ResolvExpr/ConversionCost.h

    rbdfc032 reef8dfb  
    1010// Created On       : Sun May 17 09:37:28 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Aug  8 16:13:00 2019
    13 // Update Count     : 6
     12// Last Modified On : Wed Jul 29 16:12:00 2020
     13// Update Count     : 7
    1414//
    1515
     
    5151                void postvisit( const ReferenceType * refType );
    5252                void postvisit( const FunctionType * functionType );
    53                 void postvisit( const StructInstType * aggregateUseType );
    54                 void postvisit( const UnionInstType * aggregateUseType );
    5553                void postvisit( const EnumInstType * aggregateUseType );
    5654                void postvisit( const TraitInstType * aggregateUseType );
     
    7472
    7573// Some function pointer types, differ in return type.
    76 using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *,
     74using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *, bool,
    7775        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
    78 using NumCostCalculation = std::function<int(const ast::Type *, const ast::Type *,
     76using PtrsCalculation = std::function<int(const ast::Type *, const ast::Type *,
    7977        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
    8078
     
    8381protected:
    8482        const ast::Type * dst;
     83        bool srcIsLvalue;
    8584        const ast::SymbolTable & symtab;
    8685        const ast::TypeEnvironment & env;
    8786        CostCalculation costCalc;
    8887public:
     88        static size_t traceId;
    8989        Cost cost;
     90        Cost result() { return cost; }
    9091
    91         ConversionCost_new( const ast::Type * dst, const ast::SymbolTable & symtab,
     92        ConversionCost_new( const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab,
    9293                        const ast::TypeEnvironment & env, CostCalculation costCalc ) :
    93                 dst( dst ), symtab( symtab ), env( env ), costCalc( costCalc ), cost( Cost::infinity )
     94                dst( dst ), srcIsLvalue( srcIsLvalue ), symtab( symtab ), env( env ),
     95                costCalc( costCalc ), cost( Cost::infinity )
    9496        {}
    9597
     
    102104        void postvisit( const ast::ReferenceType * refType );
    103105        void postvisit( const ast::FunctionType * functionType );
    104         void postvisit( const ast::StructInstType * structInstType );
    105         void postvisit( const ast::UnionInstType * unionInstType );
    106106        void postvisit( const ast::EnumInstType * enumInstType );
    107107        void postvisit( const ast::TraitInstType * traitInstType );
     
    114114
    115115Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,
    116         const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, NumCostCalculation func );
     116        bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env,
     117        PtrsCalculation func );
    117118
    118119} // namespace ResolvExpr
  • src/ResolvExpr/CurrentObject.cc

    rbdfc032 reef8dfb  
    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<<
     
    592594        class SimpleIterator final : public MemberIterator {
    593595                CodeLocation location;
    594                 readonly< Type > type = nullptr;
     596                const Type * type = nullptr;
    595597        public:
    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 {
     
    628630        class ArrayIterator final : public MemberIterator {
    629631                CodeLocation location;
    630                 readonly< ArrayType > array = nullptr;
    631                 readonly< Type > base = nullptr;
     632                const ArrayType * array = nullptr;
     633                const Type * base = nullptr;
    632634                size_t index = 0;
    633635                size_t size = 0;
     
    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
     
    920923
    921924        MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ) {
    922                 if ( auto aggr = dynamic_cast< const ReferenceToType * >( type ) ) {
     925                if ( auto aggr = dynamic_cast< const BaseInstType * >( type ) ) {
    923926                        if ( auto sit = dynamic_cast< const StructInstType * >( aggr ) ) {
    924927                                return new StructIterator{ loc, sit };
     
    926929                                return new UnionIterator{ loc, uit };
    927930                        } else {
    928                                 assertf( 
    929                                         dynamic_cast< const EnumInstType * >( aggr )
    930                                                 || dynamic_cast< const TypeInstType * >( aggr ),
    931                                         "Encountered unhandled ReferenceToType in createMemberIterator: %s",
     931                                assertf(
     932                                        dynamic_cast< const EnumInstType * >( type )
     933                                                || dynamic_cast< const TypeInstType * >( type ),
     934                                        "Encountered unhandled BaseInstType in createMemberIterator: %s",
    932935                                                toString( type ).c_str() );
    933936                                return new SimpleIterator{ loc, type };
     
    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;
     
    962965                                        DesignatorChain & d = *dit;
    963966                                        PRINT( std::cerr << "____actual: " << t << std::endl; )
    964                                         if ( auto refType = dynamic_cast< const ReferenceToType * >( t ) ) {
     967                                        if ( auto refType = dynamic_cast< const BaseInstType * >( t ) ) {
    965968                                                // concatenate identical field names
    966969                                                for ( const Decl * mem : refType->lookup( nexpr->name ) ) {
     
    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/FindOpenVars.cc

    rbdfc032 reef8dfb  
    112112                                // mark open/closed variables
    113113                                if ( nextIsOpen ) {
    114                                         for ( const ast::TypeDecl * decl : type->forall ) {
    115                                                 open[ decl->name ] = ast::TypeDecl::Data{ decl };
    116                                                 for ( const ast::DeclWithType * assert : decl->assertions ) {
    117                                                         need[ assert ].isUsed = false;
    118                                                 }
     114                                        for ( auto & decl : type->forall ) {
     115                                                open[ *decl ] = ast::TypeDecl::Data{ decl->base };
     116                                        }
     117                                        for ( auto & assert : type->assertions ) {
     118                                                need[ assert ].isUsed = false;
    119119                                        }
    120120                                } else {
    121                                         for ( const ast::TypeDecl * decl : type->forall ) {
    122                                                 closed[ decl->name ] = ast::TypeDecl::Data{ decl };
    123                                                 for ( const ast::DeclWithType * assert : decl->assertions ) {
    124                                                         have[ assert ].isUsed = false;
    125                                                 }
     121                                        for ( auto & decl : type->forall ) {
     122                                                closed[ *decl ] = ast::TypeDecl::Data{ decl->base };   
     123                                        }
     124                                        for ( auto & assert : type->assertions ) {
     125                                                have[ assert ].isUsed = false;
    126126                                        }
    127127                                }
  • src/ResolvExpr/PolyCost.cc

    rbdfc032 reef8dfb  
    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 ) {
    69                 if ( const ast::EqvClass * eqv = env_.lookup( type->name ) ) /* && */ if ( eqv->bound ) {
     70                if ( const ast::EqvClass * eqv = env_.lookup( *type ) ) /* && */ if ( eqv->bound ) {
    7071                        if ( const ast::TypeInstType * otherType = eqv->bound.as< ast::TypeInstType >() ) {
    7172                                if ( symtab.lookupType( otherType->name ) ) {
     
    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

    rbdfc032 reef8dfb  
    134134        }
    135135        void postvisit( const ast::TypeInstType * inst ) {
    136                 if ( const ast::EqvClass * eqv = typeEnv.lookup( inst->name ) ) {
     136                if ( const ast::EqvClass * eqv = typeEnv.lookup( *inst ) ) {
    137137                        if ( eqv->bound ) {
    138138                                // T * = S * for any S depends on the type bound to T
     
    146146                const ast::TypeEnvironment & env ) {
    147147        if ( const ast::TypeInstType * dstAsInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    148                 if ( const ast::EqvClass * eqv = env.lookup( dstAsInst->name ) ) {
     148                if ( const ast::EqvClass * eqv = env.lookup( *dstAsInst ) ) {
    149149                        return ptrsAssignable( src, eqv->bound, env );
    150150                }
     
    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

    rbdfc032 reef8dfb  
    180180                                        }
    181181                                }
    182                         } else if ( const ast::EqvClass * eqvClass = env.lookup( inst->name ) ) {
     182                        } else if ( const ast::EqvClass * eqvClass = env.lookup( *inst ) ) {
    183183                                if ( eqvClass->data.kind == ast::TypeDecl::Ftype ) {
    184184                                        return -1;
     
    283283) {
    284284        if ( auto inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    285                 if ( const ast::EqvClass * eqvClass = env.lookup( inst->name ) ) {
     285                if ( const ast::EqvClass * eqvClass = env.lookup( *inst ) ) {
    286286                        return ptrsAssignable( src, eqvClass->bound, env );
    287287                }
     
    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

    rbdfc032 reef8dfb  
    3030#include "SynTree/Visitor.h"       // for acceptAll, maybeAccept
    3131
     32#include "AST/Copy.hpp"
     33
    3234namespace ResolvExpr {
    3335
     
    3638                int level = 0;
    3739                int resetCount = 0;
     40
     41                int next_expr_id = 1;
     42                int next_usage_id = 1;
    3843                ScopedMap< std::string, std::string > nameMap;
    39 
     44                ScopedMap< std::string, ast::TypeInstType::TypeEnvKey > idMap;
    4045        public:
    4146                void reset() {
     
    4449                }
    4550
    46                 using mapConstIterator = ScopedMap< std::string, std::string >::const_iterator;
    47 
    4851                void rename( TypeInstType * type ) {
    49                         mapConstIterator it = nameMap.find( type->name );
     52                        auto it = nameMap.find( type->name );
    5053                        if ( it != nameMap.end() ) {
    5154                                type->name = it->second;
    5255                        }
     56                }
     57
     58                void nextUsage() {
     59                        ++next_usage_id;
    5360                }
    5461
     
    6572                                        // ditto for assertion names, the next level in
    6673                                        level++;
    67                                         // acceptAll( td->assertions, *this );
    68                                 } // for
    69                         } // if
     74                                }
     75                        }
    7076                }
    7177
     
    7783
    7884                const ast::TypeInstType * rename( const ast::TypeInstType * type ) {
    79                         mapConstIterator it = nameMap.find( type->name );
    80                         if ( it != nameMap.end() ) {
    81                                 ast::TypeInstType * mutType = ast::mutate( type );
    82                                 mutType->name = it->second;
    83                     type = mutType;
    84                         }
     85                        // rename
     86                        auto it = idMap.find( type->name );
     87                        if ( it != idMap.end() ) {
     88                                // unconditionally mutate because map will *always* have different name
     89                                ast::TypeInstType * mut = ast::shallowCopy( type );
     90                                // reconcile base node since some copies might have been made
     91                                mut->base = it->second.base;
     92                                mut->formal_usage = it->second.formal_usage;
     93                                mut->expr_id = it->second.expr_id;
     94                    type = mut;
     95                        }
     96
    8597                        return type;
    8698                }
    8799
    88                 template<typename NodeT>
    89                 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;
    100 
    101                                         ast::TypeDecl * decl = ast::mutate( td.get() );
    102                                         decl->name = newname;
    103                                         td = decl;
    104                                 }
    105                         }
    106                         return type;
    107                 }
    108 
    109                 template<typename NodeT>
    110                 const NodeT * closeLevel( const NodeT * type ) {
    111                         if ( !type->forall.empty() ) {
    112                                 nameMap.endScope();
    113                         }
    114                         return type;
     100                const ast::FunctionType * openLevel( const ast::FunctionType * type, RenameMode mode ) {
     101                        if ( type->forall.empty() ) return type;
     102                        idMap.beginScope();
     103
     104                        // Load new names from this forall clause and perform renaming.
     105                        auto mutType = ast::shallowCopy( type );
     106                        // assert( type == mutType && "mutated type must be unique from ForallSubstitutor" );
     107                        for ( auto & td : mutType->forall ) {
     108                                auto mut = ast::shallowCopy( td.get() );
     109                                // assert( td == mutDecl && "mutated decl must be unique from ForallSubstitutor" );
     110
     111                                if (mode == GEN_EXPR_ID) {
     112                                        mut->expr_id = next_expr_id;
     113                                        mut->formal_usage = -1;
     114                                        ++next_expr_id;
     115                                }
     116                                else if (mode == GEN_USAGE) {
     117                                        assertf(mut->expr_id, "unfilled expression id in generating candidate type");
     118                                        mut->formal_usage = next_usage_id;
     119                                }
     120                                else {
     121                                        assert(false);
     122                                }
     123                                idMap[ td->name ] = ast::TypeInstType::TypeEnvKey(*mut);
     124                               
     125                                td = mut;
     126                        }
     127
     128                        return mutType;
     129                }
     130
     131                void closeLevel( const ast::FunctionType * type ) {
     132                        if ( type->forall.empty() ) return;
     133                        idMap.endScope();
    115134                }
    116135        };
     
    119138        RenamingData renaming;
    120139
    121         struct RenameVars {
     140        struct RenameVars_old {
    122141                void previsit( TypeInstType * instType ) {
    123142                        renaming.openLevel( (Type*)instType );
     
    130149                        renaming.closeLevel( type );
    131150                }
     151        };
     152
     153        struct RenameVars_new : public ast::PureVisitor /*: public ast::WithForallSubstitutor*/ {
     154                RenameMode mode;
    132155
    133156                const ast::FunctionType * previsit( const ast::FunctionType * type ) {
    134                         return renaming.openLevel( type );
    135                 }
     157                        return renaming.openLevel( type, mode );
     158                }
     159
     160                /*
    136161                const ast::StructInstType * previsit( const ast::StructInstType * type ) {
    137162                        return renaming.openLevel( type );
     
    143168                        return renaming.openLevel( type );
    144169                }
     170                */
     171
    145172                const ast::TypeInstType * previsit( const ast::TypeInstType * type ) {
    146                         return renaming.rename( renaming.openLevel( type ) );
    147                 }
    148                 const ast::ParameterizedType * postvisit( const ast::ParameterizedType * type ) {
    149                         return renaming.closeLevel( type );
     173                        if (mode == GEN_USAGE && !type->formal_usage) return type; // do not rename an actual type
     174                        return renaming.rename( type );
     175                }
     176                void postvisit( const ast::FunctionType * type ) {
     177                        renaming.closeLevel( type );
    150178                }
    151179        };
     
    154182
    155183void renameTyVars( Type * t ) {
    156         PassVisitor<RenameVars> renamer;
     184        PassVisitor<RenameVars_old> renamer;
    157185        t->accept( renamer );
    158186}
    159187
    160 const ast::Type * renameTyVars( const ast::Type * t ) {
    161         ast::Pass<RenameVars> renamer;
     188const ast::Type * renameTyVars( const ast::Type * t, RenameMode mode, bool reset ) {
     189        // ast::Type *tc = ast::deepCopy(t);
     190        ast::Pass<RenameVars_new> renamer;
     191        renamer.core.mode = mode;
     192        if (mode == GEN_USAGE && reset) {
     193                renaming.nextUsage();
     194        }
    162195        return t->accept( renamer );
    163196}
     
    165198void resetTyVarRenaming() {
    166199        renaming.reset();
     200        renaming.nextUsage();
    167201}
    168202
  • src/ResolvExpr/RenameVars.h

    rbdfc032 reef8dfb  
    3030        /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID
    3131        void renameTyVars( Type * );
    32         const ast::Type * renameTyVars( const ast::Type * );
     32
     33        enum RenameMode {
     34                GEN_USAGE, // for type in VariableExpr
     35                GEN_EXPR_ID // for type in decl
     36        };
     37        const ast::Type * renameTyVars( const ast::Type *, RenameMode mode = GEN_USAGE, bool reset = true );
     38       
    3339
    3440        /// resets internal state of renamer to avoid overflow
    3541        void resetTyVarRenaming();
     42
     43       
    3644} // namespace ResolvExpr
    3745
  • src/ResolvExpr/ResolvMode.h

    rbdfc032 reef8dfb  
    2222                const bool prune;            ///< Prune alternatives to min-cost per return type? [true]
    2323                const bool failFast;         ///< Fail on no resulting alternatives? [true]
    24                 const bool satisfyAssns;     ///< Satisfy assertions? [false]
    2524
    26         private:
    27                 constexpr ResolvMode(bool a, bool p, bool ff, bool sa)
    28                 : adjust(a), prune(p), failFast(ff), satisfyAssns(sa) {}
     25                constexpr ResolvMode(bool a, bool p, bool ff)
     26                : adjust(a), prune(p), failFast(ff) {}
    2927
    30         public:
    3128                /// Default settings
    32                 constexpr ResolvMode() : adjust(false), prune(true), failFast(true), satisfyAssns(false) {}
     29                constexpr ResolvMode() : adjust(false), prune(true), failFast(true) {}
    3330               
    3431                /// With adjust flag set; turns array and function types into equivalent pointers
    35                 static constexpr ResolvMode withAdjustment() { return { true, true, true, false }; }
     32                static constexpr ResolvMode withAdjustment() { return { true, true, true }; }
    3633
    3734                /// With adjust flag set but prune unset; pruning ensures there is at least one alternative
    3835                /// per result type
    39                 static constexpr ResolvMode withoutPrune() { return { true, false, true, false }; }
     36                static constexpr ResolvMode withoutPrune() { return { true, false, true }; }
    4037
    4138                /// With adjust and prune flags set but failFast unset; failFast ensures there is at least
    4239                /// one resulting alternative
    43                 static constexpr ResolvMode withoutFailFast() { return { true, true, false, false }; }
     40                static constexpr ResolvMode withoutFailFast() { return { true, true, false }; }
    4441
    4542                /// The same mode, but with satisfyAssns turned on; for top-level calls
    46                 ResolvMode atTopLevel() const { return { adjust, prune, failFast, true }; }
     43                ResolvMode atTopLevel() const { return { adjust, true, failFast }; }
    4744        };
    4845} // namespace ResolvExpr
  • src/ResolvExpr/ResolveAssertions.cc

    rbdfc032 reef8dfb  
    277277                        const DeclarationWithType * candidate = cdata.id;
    278278
    279                         // build independent unification context for candidate
     279                        // ignore deleted candidates.
     280                        // NOTE: this behavior is different from main resolver.
     281                        // further investigations might be needed to determine
     282                        // if we should implement the same rule here
     283                        // (i.e. error if unique best match is deleted)
     284                        if (candidate->isDeleted) continue;
     285
     286                        // build independent unification context. for candidate
    280287                        AssertionSet have, newNeed;
    281288                        TypeEnvironment newEnv{ resn.alt.env };
  • src/ResolvExpr/ResolveTypeof.cc

    rbdfc032 reef8dfb  
    1515
    1616#include "ResolveTypeof.h"
     17#include "RenameVars.h"
    1718
    1819#include <cassert>               // for assert
     
    2930#include "SynTree/Mutator.h"     // for Mutator
    3031#include "SynTree/Type.h"        // for TypeofType, Type
     32#include "SymTab/Mangler.h"
     33#include "InitTweak/InitTweak.h" // for isConstExpr
    3134
    3235namespace SymTab {
     
    99102                        // replace basetypeof(<enum>) by int
    100103                        if ( dynamic_cast<EnumInstType*>(newType) ) {
    101                                 Type* newerType = 
    102                                         new BasicType{ newType->get_qualifiers(), BasicType::SignedInt, 
     104                                Type* newerType =
     105                                        new BasicType{ newType->get_qualifiers(), BasicType::SignedInt,
    103106                                        newType->attributes };
    104107                                delete newType;
    105108                                newType = newerType;
    106109                        }
    107                         newType->get_qualifiers().val 
     110                        newType->get_qualifiers().val
    108111                                = ( newType->get_qualifiers().val & ~Type::Qualifiers::Mask ) | oldQuals;
    109112                } else {
    110113                        newType->get_qualifiers().val |= oldQuals;
    111114                }
    112                
     115
    113116                return newType;
    114117        }
     
    120123                ResolveTypeof_new( const ast::SymbolTable & syms ) : localSymtab( syms ) {}
    121124
    122                 void premutate( const ast::TypeofType * ) { visit_children = false; }
    123 
    124                 const ast::Type * postmutate( const ast::TypeofType * typeofType ) {
     125                void previsit( const ast::TypeofType * ) { visit_children = false; }
     126
     127                const ast::Type * postvisit( const ast::TypeofType * typeofType ) {
    125128                        // pass on null expression
    126129                        if ( ! typeofType->expr ) return typeofType;
     
    133136                                // typeof wrapping expression
    134137                                ast::TypeEnvironment dummy;
    135                                 ast::ptr< ast::Expr > newExpr = 
     138                                ast::ptr< ast::Expr > newExpr =
    136139                                        resolveInVoidContext( typeofType->expr, localSymtab, dummy );
    137140                                assert( newExpr->result && ! newExpr->result->isVoid() );
     
    143146                                // replace basetypeof(<enum>) by int
    144147                                if ( newType.as< ast::EnumInstType >() ) {
    145                                         newType = new ast::BasicType{ 
     148                                        newType = new ast::BasicType{
    146149                                                ast::BasicType::SignedInt, newType->qualifiers, copy(newType->attributes) };
    147150                                }
    148                                 reset_qualifiers( 
    149                                         newType, 
     151                                reset_qualifiers(
     152                                        newType,
    150153                                        ( newType->qualifiers & ~ast::CV::EquivQualifiers ) | typeofType->qualifiers );
    151154                        } else {
     
    153156                        }
    154157
    155                         return newType;
     158                        return newType.release();
    156159                }
    157160        };
     
    161164        ast::Pass< ResolveTypeof_new > mutator{ symtab };
    162165        return type->accept( mutator );
     166}
     167
     168struct FixArrayDimension {
     169        // should not require a mutable symbol table - prevent pass template instantiation
     170        const ast::SymbolTable & _symtab;
     171        FixArrayDimension(const ast::SymbolTable & symtab): _symtab(symtab) {}
     172
     173        const ast::ArrayType * previsit (const ast::ArrayType * arrayType) {
     174                if (!arrayType->dimension) return arrayType;
     175                auto mutType = mutate(arrayType);
     176                ast::ptr<ast::Type> sizetype = ast::sizeType ? ast::sizeType : new ast::BasicType(ast::BasicType::LongUnsignedInt);
     177                mutType->dimension = findSingleExpression(arrayType->dimension, sizetype, _symtab);
     178
     179                if (InitTweak::isConstExpr(mutType->dimension)) {
     180                        mutType->isVarLen = ast::LengthFlag::FixedLen;
     181                }
     182                else {
     183                        mutType->isVarLen = ast::LengthFlag::VariableLen;
     184                }
     185                return mutType;
     186        }
     187};
     188
     189const ast::Type * fixArrayType( const ast::Type * type, const ast::SymbolTable & symtab) {
     190        ast::Pass<FixArrayDimension> visitor {symtab};
     191        return type->accept(visitor);
     192}
     193
     194const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ast::SymbolTable & symtab ) {
     195        if (!decl->isTypeFixed) {
     196                auto mutDecl = mutate(decl);
     197                auto resolvedType = resolveTypeof(decl->type, symtab);
     198                resolvedType = fixArrayType(resolvedType, symtab);
     199                mutDecl->type = resolvedType;
     200
     201                // check variable length if object is an array.
     202                // xxx - should this be part of fixObjectType?
     203
     204                /*
     205                if (auto arrayType = dynamic_cast<const ast::ArrayType *>(resolvedType)) {
     206                        auto dimExpr = findSingleExpression(arrayType->dimension, ast::sizeType, symtab);
     207                        if (auto varexpr = arrayType->dimension.as<ast::VariableExpr>()) {// hoisted previously
     208                                if (InitTweak::isConstExpr(varexpr->var.strict_as<ast::ObjectDecl>()->init)) {
     209                                        auto mutType = mutate(arrayType);
     210                                        mutType->isVarLen = ast::LengthFlag::VariableLen;
     211                                        mutDecl->type = mutType;
     212                                }
     213                        }
     214                }
     215                */
     216
     217
     218                if (!mutDecl->name.empty())
     219                        mutDecl->mangleName = Mangle::mangle(mutDecl); // do not mangle unnamed variables
     220               
     221                mutDecl->type = renameTyVars(mutDecl->type, RenameMode::GEN_EXPR_ID);
     222                mutDecl->isTypeFixed = true;
     223                return mutDecl;
     224        }
     225        return decl;
    163226}
    164227
  • src/ResolvExpr/ResolveTypeof.h

    rbdfc032 reef8dfb  
    2323        class Type;
    2424        class SymbolTable;
     25        class ObjectDecl;
    2526}
    2627
     
    2829        Type *resolveTypeof( Type*, const SymTab::Indexer &indexer );
    2930        const ast::Type * resolveTypeof( const ast::Type *, const ast::SymbolTable & );
     31        const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ast::SymbolTable & symtab );
    3032} // namespace ResolvExpr
    3133
  • src/ResolvExpr/Resolver.cc

    rbdfc032 reef8dfb  
    99// Author           : Aaron B. Moss
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Wed May 29 11:00:00 2019
    13 // Update Count     : 241
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Mar 27 11:58:00 2020
     13// Update Count     : 242
    1414//
    1515
     
    2626#include "RenameVars.h"                  // for RenameVars, global_renamer
    2727#include "Resolver.h"
     28#include "ResolveTypeof.h"
    2829#include "ResolvMode.h"                  // for ResolvMode
    2930#include "typeops.h"                     // for extractResultType
    3031#include "Unify.h"                       // for unify
     32#include "CompilationState.h"
    3133#include "AST/Chain.hpp"
    3234#include "AST/Decl.hpp"
     
    3840#include "Common/PassVisitor.h"          // for PassVisitor
    3941#include "Common/SemanticError.h"        // for SemanticError
     42#include "Common/Stats/ResolveTime.h"    // for ResolveTime::start(), ResolveTime::stop()
    4043#include "Common/utility.h"              // for ValueGuard, group_iterate
    4144#include "InitTweak/GenInit.h"
     
    4447#include "SymTab/Autogen.h"              // for SizeType
    4548#include "SymTab/Indexer.h"              // for Indexer
     49#include "SymTab/Mangler.h"              // for Mangler
    4650#include "SynTree/Declaration.h"         // for ObjectDecl, TypeDecl, Declar...
    4751#include "SynTree/Expression.h"          // for Expression, CastExpr, InitExpr
     
    8488                void previsit( ThrowStmt * throwStmt );
    8589                void previsit( CatchStmt * catchStmt );
     90                void postvisit( CatchStmt * catchStmt );
    8691                void previsit( WaitForStmt * stmt );
    8792
     
    559564                // TODO: Replace *exception type with &exception type.
    560565                if ( throwStmt->get_expr() ) {
    561                         const StructDecl * exception_decl = indexer.lookupStruct( "__cfaabi_ehm__base_exception_t" );
     566                        const StructDecl * exception_decl = indexer.lookupStruct( "__cfaehm_base_exception_t" );
    562567                        assert( exception_decl );
    563568                        Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, const_cast<StructDecl *>(exception_decl) ) );
     
    567572
    568573        void Resolver_old::previsit( CatchStmt * catchStmt ) {
     574                // Until we are very sure this invarent (ifs that move between passes have thenPart)
     575                // holds, check it. This allows a check for when to decode the mangling.
     576                if ( IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body ) ) {
     577                        assert( ifStmt->thenPart );
     578                }
     579                // Encode the catchStmt so the condition can see the declaration.
    569580                if ( catchStmt->cond ) {
    570                         findSingleExpression( catchStmt->cond, new BasicType( noQualifiers, BasicType::Bool ), indexer );
     581                        IfStmt * ifStmt = new IfStmt( catchStmt->cond, nullptr, catchStmt->body );
     582                        catchStmt->cond = nullptr;
     583                        catchStmt->body = ifStmt;
     584                }
     585        }
     586
     587        void Resolver_old::postvisit( CatchStmt * catchStmt ) {
     588                // Decode the catchStmt so everything is stored properly.
     589                IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body );
     590                if ( nullptr != ifStmt && nullptr == ifStmt->thenPart ) {
     591                        assert( ifStmt->condition );
     592                        assert( ifStmt->elsePart );
     593                        catchStmt->cond = ifStmt->condition;
     594                        catchStmt->body = ifStmt->elsePart;
     595                        ifStmt->condition = nullptr;
     596                        ifStmt->elsePart = nullptr;
     597                        delete ifStmt;
    571598                }
    572599        }
     
    941968        namespace {
    942969                /// Finds deleted expressions in an expression tree
    943                 struct DeleteFinder_new final : public ast::WithShortCircuiting {
    944                         const ast::DeletedExpr * delExpr = nullptr;
     970                struct DeleteFinder_new final : public ast::WithShortCircuiting, public ast::WithVisitorRef<DeleteFinder_new> {
     971                        const ast::DeletedExpr * result = nullptr;
    945972
    946973                        void previsit( const ast::DeletedExpr * expr ) {
    947                                 if ( delExpr ) { visit_children = false; }
    948                                 else { delExpr = expr; }
    949                         }
    950 
    951                         void previsit( const ast::Expr * ) {
    952                                 if ( delExpr ) { visit_children = false; }
     974                                if ( result ) { visit_children = false; }
     975                                else { result = expr; }
     976                        }
     977
     978                        void previsit( const ast::Expr * expr ) {
     979                                if ( result ) { visit_children = false; }
     980                                if (expr->inferred.hasParams()) {
     981                                        for (auto & imp : expr->inferred.inferParams() ) {
     982                                                imp.second.expr->accept(*visitor);
     983                                        }
     984                                }
    953985                        }
    954986                };
    955987        } // anonymous namespace
    956 
    957988        /// Check if this expression is or includes a deleted expression
    958989        const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) {
    959                 ast::Pass<DeleteFinder_new> finder;
    960                 expr->accept( finder );
    961                 return finder.pass.delExpr;
     990                return ast::Pass<DeleteFinder_new>::read( expr );
    962991        }
    963992
     
    10491078                /// Strips extraneous casts out of an expression
    10501079                struct StripCasts_new final {
    1051                         const ast::Expr * postmutate( const ast::CastExpr * castExpr ) {
     1080                        const ast::Expr * postvisit( const ast::CastExpr * castExpr ) {
    10521081                                if (
    1053                                         castExpr->isGenerated
     1082                                        castExpr->isGenerated == ast::GeneratedCast
    10541083                                        && typesCompatible( castExpr->arg->result, castExpr->result )
    10551084                                ) {
     
    10831112                }
    10841113
    1085                 /// Establish post-resolver invariants for expressions
     1114               
     1115        } // anonymous namespace
     1116/// Establish post-resolver invariants for expressions
    10861117                void finishExpr(
    10871118                        ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env,
     
    10961127                        StripCasts_new::strip( expr );
    10971128                }
    1098         } // anonymous namespace
    1099 
    11001129
    11011130        ast::ptr< ast::Expr > resolveInVoidContext(
     
    11051134
    11061135                // set up and resolve expression cast to void
    1107                 ast::CastExpr * untyped = new ast::CastExpr{ expr };
     1136                ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
    11081137                CandidateRef choice = findUnfinishedKindExpression(
    11091138                        untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
     
    11171146        }
    11181147
    1119         namespace {
    1120                 /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
     1148        /// Resolve `untyped` to the expression whose candidate is the best match for a `void`
    11211149                /// context.
    11221150                ast::ptr< ast::Expr > findVoidExpression(
    11231151                        const ast::Expr * untyped, const ast::SymbolTable & symtab
    11241152                ) {
    1125                         resetTyVarRenaming();
    11261153                        ast::TypeEnvironment env;
    11271154                        ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env );
     
    11291156                        return newExpr;
    11301157                }
     1158
     1159        namespace {
     1160               
    11311161
    11321162                /// resolve `untyped` to the expression whose candidate satisfies `pred` with the
     
    11401170                        CandidateRef choice =
    11411171                                findUnfinishedKindExpression( untyped, symtab, kind, pred, mode );
    1142                         finishExpr( choice->expr, choice->env, untyped->env );
     1172                        ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env );
    11431173                        return std::move( choice->expr );
    11441174                }
     
    11481178                        const ast::Expr * untyped, const ast::SymbolTable & symtab
    11491179                ) {
    1150                         return findKindExpression( untyped, symtab );
     1180                        Stats::ResolveTime::start( untyped );
     1181                        auto res = findKindExpression( untyped, symtab );
     1182                        Stats::ResolveTime::stop();
     1183                        return res;
    11511184                }
    11521185        } // anonymous namespace
    11531186
    1154                 ast::ptr< ast::Expr > findSingleExpression(
    1155                         const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
    1156                 ) {
    1157                         assert( untyped && type );
    1158                         ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
    1159                         ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
    1160                         removeExtraneousCast( newExpr, symtab );
    1161                         return newExpr;
    1162                 }
     1187        ast::ptr< ast::Expr > findSingleExpression(
     1188                const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
     1189        ) {
     1190                assert( untyped && type );
     1191                ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
     1192                ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
     1193                removeExtraneousCast( newExpr, symtab );
     1194                return newExpr;
     1195        }
    11631196
    11641197        namespace {
     1198                bool structOrUnion( const Candidate & i ) {
     1199                        const ast::Type * t = i.expr->result->stripReferences();
     1200                        return dynamic_cast< const ast::StructInstType * >( t ) || dynamic_cast< const ast::UnionInstType * >( t );
     1201                }
    11651202                /// Predicate for "Candidate has integral type"
    11661203                bool hasIntegralType( const Candidate & i ) {
     
    11981235                template<typename Iter>
    11991236                inline bool nextMutex( Iter & it, const Iter & end ) {
    1200                         while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; }
     1237                        while ( it != end && ! (*it)->is_mutex() ) { ++it; }
    12011238                        return it != end;
    12021239                }
     
    12101247                ast::ptr< ast::Type > functionReturn = nullptr;
    12111248                ast::CurrentObject currentObject;
     1249                // for work previously in GenInit
     1250                static InitTweak::ManagedTypes_new managedTypes;
     1251
    12121252                bool inEnumDecl = false;
    12131253
    12141254        public:
     1255                static size_t traceId;
    12151256                Resolver_new() = default;
    12161257                Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
    12171258
    1218                 void previsit( const ast::FunctionDecl * );
     1259                const ast::FunctionDecl * previsit( const ast::FunctionDecl * );
    12191260                const ast::FunctionDecl * postvisit( const ast::FunctionDecl * );
    1220                 void previsit( const ast::ObjectDecl * );
     1261                const ast::ObjectDecl * previsit( const ast::ObjectDecl * );
     1262                void previsit( const ast::AggregateDecl * );
     1263                void previsit( const ast::StructDecl * );
    12211264                void previsit( const ast::EnumDecl * );
    12221265                const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * );
     
    12371280                const ast::ThrowStmt *       previsit( const ast::ThrowStmt * );
    12381281                const ast::CatchStmt *       previsit( const ast::CatchStmt * );
     1282                const ast::CatchStmt *       postvisit( const ast::CatchStmt * );
    12391283                const ast::WaitForStmt *     previsit( const ast::WaitForStmt * );
     1284                const ast::WithStmt *        previsit( const ast::WithStmt * );
    12401285
    12411286                const ast::SingleInit *      previsit( const ast::SingleInit * );
    12421287                const ast::ListInit *        previsit( const ast::ListInit * );
    12431288                const ast::ConstructorInit * previsit( const ast::ConstructorInit * );
     1289
     1290                void resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd);
     1291
     1292                void beginScope() { managedTypes.beginScope(); }
     1293                void endScope() { managedTypes.endScope(); }
     1294                bool on_error(ast::ptr<ast::Decl> & decl);
    12441295        };
    1245 
    1246         void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) {
    1247                 ast::Pass< Resolver_new > resolver;
    1248                 accept_all( translationUnit, resolver );
     1296        // size_t Resolver_new::traceId = Stats::Heap::new_stacktrace_id("Resolver");
     1297
     1298        InitTweak::ManagedTypes_new Resolver_new::managedTypes;
     1299
     1300        void resolve( ast::TranslationUnit& translationUnit ) {
     1301                ast::Pass< Resolver_new >::run( translationUnit );
    12491302        }
    12501303
     
    12571310        }
    12581311
    1259         ast::ptr< ast::Expr > resolveStmtExpr(
     1312        const ast::Expr * resolveStmtExpr(
    12601313                const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab
    12611314        ) {
    12621315                assert( stmtExpr );
    12631316                ast::Pass< Resolver_new > resolver{ symtab };
    1264                 ast::ptr< ast::Expr > ret = stmtExpr;
    1265                 ret = ret->accept( resolver );
    1266                 strict_dynamic_cast< ast::StmtExpr * >( ret.get_and_mutate() )->computeResult();
     1317                auto ret = mutate(stmtExpr->accept(resolver));
     1318                strict_dynamic_cast< ast::StmtExpr * >( ret )->computeResult();
    12671319                return ret;
    12681320        }
    12691321
    1270         void Resolver_new::previsit( const ast::FunctionDecl * functionDecl ) {
     1322        namespace {
     1323                const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ast::SymbolTable & symtab) {
     1324                        std::string name = attr->normalizedName();
     1325                        if (name == "constructor" || name == "destructor") {
     1326                                if (attr->params.size() == 1) {
     1327                                        auto arg = attr->params.front();
     1328                                        auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), symtab );
     1329                                        auto result = eval(arg);
     1330
     1331                                        auto mutAttr = mutate(attr);
     1332                                        mutAttr->params.front() = resolved;
     1333                                        if (! result.second) {
     1334                                                SemanticWarning(loc, Warning::GccAttributes,
     1335                                                        toCString( name, " priorities must be integers from 0 to 65535 inclusive: ", arg ) );
     1336                                        }
     1337                                        else {
     1338                                                auto priority = result.first;
     1339                                                if (priority < 101) {
     1340                                                        SemanticWarning(loc, Warning::GccAttributes,
     1341                                                                toCString( name, " priorities from 0 to 100 are reserved for the implementation" ) );
     1342                                                } else if (priority < 201 && ! buildingLibrary()) {
     1343                                                        SemanticWarning(loc, Warning::GccAttributes,
     1344                                                                toCString( name, " priorities from 101 to 200 are reserved for the implementation" ) );
     1345                                                }
     1346                                        }
     1347                                        return mutAttr;
     1348                                } else if (attr->params.size() > 1) {
     1349                                        SemanticWarning(loc, Warning::GccAttributes, toCString( "too many arguments to ", name, " attribute" ) );
     1350                                } else {
     1351                                        SemanticWarning(loc, Warning::GccAttributes, toCString( "too few arguments to ", name, " attribute" ) );
     1352                                }
     1353                        }
     1354                        return attr;
     1355                }
     1356        }
     1357
     1358        const ast::FunctionDecl * Resolver_new::previsit( const ast::FunctionDecl * functionDecl ) {
    12711359                GuardValue( functionReturn );
     1360
     1361                assert (functionDecl->unique());
     1362                if (!functionDecl->has_body() && !functionDecl->withExprs.empty()) {
     1363                        SemanticError(functionDecl->location, functionDecl, "Function without body has with declarations");
     1364                }
     1365
     1366                if (!functionDecl->isTypeFixed) {
     1367                        auto mutDecl = mutate(functionDecl);
     1368                        auto mutType = mutDecl->type.get_and_mutate();
     1369
     1370                        for (auto & attr: mutDecl->attributes) {
     1371                                attr = handleAttribute(mutDecl->location, attr, symtab);
     1372                        }
     1373
     1374                        // handle assertions
     1375
     1376                        symtab.enterScope();
     1377                        mutType->forall.clear();
     1378                        mutType->assertions.clear();
     1379                        for (auto & typeParam : mutDecl->type_params) {
     1380                                symtab.addType(typeParam);
     1381                                mutType->forall.emplace_back(new ast::TypeInstType(typeParam->name, typeParam));
     1382                        }
     1383                        for (auto & asst : mutDecl->assertions) {
     1384                                asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), symtab);
     1385                                symtab.addId(asst);
     1386                                mutType->assertions.emplace_back(new ast::VariableExpr(functionDecl->location, asst));
     1387                        }
     1388
     1389                        // temporarily adds params to symbol table.
     1390                        // actual scoping rules for params and withexprs differ - see Pass::visit(FunctionDecl)
     1391
     1392                        std::vector<ast::ptr<ast::Type>> paramTypes;
     1393                        std::vector<ast::ptr<ast::Type>> returnTypes;
     1394
     1395                        for (auto & param : mutDecl->params) {
     1396                                param = fixObjectType(param.strict_as<ast::ObjectDecl>(), symtab);
     1397                                symtab.addId(param);
     1398                                paramTypes.emplace_back(param->get_type());
     1399                        }
     1400                        for (auto & ret : mutDecl->returns) {
     1401                                ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), symtab);
     1402                                returnTypes.emplace_back(ret->get_type());
     1403                        }
     1404                        // since function type in decl is just a view of param types, need to update that as well
     1405                        mutType->params = std::move(paramTypes);
     1406                        mutType->returns = std::move(returnTypes);
     1407
     1408                        auto renamedType = strict_dynamic_cast<const ast::FunctionType *>(renameTyVars(mutType, RenameMode::GEN_EXPR_ID));
     1409
     1410                        std::list<ast::ptr<ast::Stmt>> newStmts;
     1411                        resolveWithExprs (mutDecl->withExprs, newStmts);
     1412
     1413                        if (mutDecl->stmts) {
     1414                                auto mutStmt = mutDecl->stmts.get_and_mutate();
     1415                                mutStmt->kids.splice(mutStmt->kids.begin(), std::move(newStmts));
     1416                                mutDecl->stmts = mutStmt;
     1417                        }
     1418
     1419                        symtab.leaveScope();
     1420
     1421                        mutDecl->type = renamedType;
     1422                        mutDecl->mangleName = Mangle::mangle(mutDecl);
     1423                        mutDecl->isTypeFixed = true;
     1424                        functionDecl = mutDecl;
     1425                }
     1426                managedTypes.handleDWT(functionDecl);
     1427
    12721428                functionReturn = extractResultType( functionDecl->type );
     1429                return functionDecl;
    12731430        }
    12741431
     
    12761433                // default value expressions have an environment which shouldn't be there and trips up
    12771434                // later passes.
    1278                 ast::ptr< ast::FunctionDecl > ret = functionDecl;
    1279                 for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {
    1280                         const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i];
    1281 
    1282                         if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {
     1435                assert( functionDecl->unique() );
     1436                ast::FunctionType * mutType = mutate( functionDecl->type.get() );
     1437
     1438                for ( unsigned i = 0 ; i < mutType->params.size() ; ++i ) {
     1439                        if ( const ast::ObjectDecl * obj = mutType->params[i].as< ast::ObjectDecl >() ) {
    12831440                                if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) {
    12841441                                        if ( init->value->env == nullptr ) continue;
    12851442                                        // clone initializer minus the initializer environment
    1286                                         ast::chain_mutate( ret )
    1287                                                 ( &ast::FunctionDecl::type )
    1288                                                         ( &ast::FunctionType::params )[i]
    1289                                                                 ( &ast::ObjectDecl::init )
    1290                                                                         ( &ast::SingleInit::value )->env = nullptr;
    1291 
    1292                                         assert( functionDecl != ret.get() || functionDecl->unique() );
    1293                                         assert( ! ret->type->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env );
     1443                                        auto mutParam = mutate( mutType->params[i].strict_as< ast::ObjectDecl >() );
     1444                                        auto mutInit = mutate( mutParam->init.strict_as< ast::SingleInit >() );
     1445                                        auto mutValue = mutate( mutInit->value.get() );
     1446
     1447                                        mutValue->env = nullptr;
     1448                                        mutInit->value = mutValue;
     1449                                        mutParam->init = mutInit;
     1450                                        mutType->params[i] = mutParam;
     1451
     1452                                        assert( ! mutType->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env);
    12941453                                }
    12951454                        }
    12961455                }
    1297                 return ret.get();
    1298         }
    1299 
    1300         void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
     1456                mutate_field(functionDecl, &ast::FunctionDecl::type, mutType);
     1457                return functionDecl;
     1458        }
     1459
     1460        const ast::ObjectDecl * Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
    13011461                // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()],
    13021462                // class-variable `initContext` is changed multiple times because the LHS is analyzed
     
    13061466                // selecting the RHS.
    13071467                GuardValue( currentObject );
    1308                 currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };
     1468
    13091469                if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) {
    13101470                        // enumerator initializers should not use the enum type to initialize, since the
    13111471                        // enum type is still incomplete at this point. Use `int` instead.
     1472                        objectDecl = fixObjectType(objectDecl, symtab);
    13121473                        currentObject = ast::CurrentObject{
    13131474                                objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
    13141475                }
     1476                else {
     1477                        if (!objectDecl->isTypeFixed) {
     1478                                auto newDecl = fixObjectType(objectDecl, symtab);
     1479                                auto mutDecl = mutate(newDecl);
     1480
     1481                                // generate CtorInit wrapper when necessary.
     1482                                // in certain cases, fixObjectType is called before reaching
     1483                                // this object in visitor pass, thus disabling CtorInit codegen.
     1484                                // this happens on aggregate members and function parameters.
     1485                                if ( InitTweak::tryConstruct( mutDecl ) && ( managedTypes.isManaged( mutDecl ) || ((! isInFunction() || mutDecl->storage.is_static ) && ! InitTweak::isConstExpr( mutDecl->init ) ) ) ) {
     1486                                        // constructed objects cannot be designated
     1487                                        if ( InitTweak::isDesignated( mutDecl->init ) ) SemanticError( mutDecl, "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n" );
     1488                                        // constructed objects should not have initializers nested too deeply
     1489                                        if ( ! InitTweak::checkInitDepth( mutDecl ) ) SemanticError( mutDecl, "Managed object's initializer is too deep " );
     1490
     1491                                        mutDecl->init = InitTweak::genCtorInit( mutDecl->location, mutDecl );
     1492                                }
     1493
     1494                                objectDecl = mutDecl;
     1495                        }
     1496                        currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };
     1497                }
     1498
     1499                return objectDecl;
     1500        }
     1501
     1502        void Resolver_new::previsit( const ast::AggregateDecl * _aggDecl ) {
     1503                auto aggDecl = mutate(_aggDecl);
     1504                assertf(aggDecl == _aggDecl, "type declarations must be unique");
     1505
     1506                for (auto & member: aggDecl->members) {
     1507                        // nested type decls are hoisted already. no need to do anything
     1508                        if (auto obj = member.as<ast::ObjectDecl>()) {
     1509                                member = fixObjectType(obj, symtab);
     1510                        }
     1511                }
     1512        }
     1513
     1514        void Resolver_new::previsit( const ast::StructDecl * structDecl ) {
     1515                previsit(static_cast<const ast::AggregateDecl *>(structDecl));
     1516                managedTypes.handleStruct(structDecl);
    13151517        }
    13161518
     
    13181520                // in case we decide to allow nested enums
    13191521                GuardValue( inEnumDecl );
    1320                 inEnumDecl = false;
    1321         }
     1522                inEnumDecl = true;
     1523                // don't need to fix types for enum fields
     1524        }
     1525
    13221526
    13231527        const ast::StaticAssertDecl * Resolver_new::previsit(
     
    13321536        const PtrType * handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) {
    13331537                if ( type->dimension ) {
    1334                         #warning should use new equivalent to Validate::SizeType rather than sizeType here
    1335                         ast::ptr< ast::Type > sizeType = new ast::BasicType{ ast::BasicType::LongUnsignedInt };
     1538                        ast::ptr< ast::Type > sizeType = ast::sizeType;
    13361539                        ast::mutate_field(
    13371540                                type, &PtrType::dimension,
     
    14541657                if ( throwStmt->expr ) {
    14551658                        const ast::StructDecl * exceptionDecl =
    1456                                 symtab.lookupStruct( "__cfaabi_ehm__base_exception_t" );
     1659                                symtab.lookupStruct( "__cfaehm_base_exception_t" );
    14571660                        assert( exceptionDecl );
    14581661                        ast::ptr< ast::Type > exceptType =
     
    14661669
    14671670        const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) {
     1671                // Until we are very sure this invarent (ifs that move between passes have thenPart)
     1672                // holds, check it. This allows a check for when to decode the mangling.
     1673                if ( auto ifStmt = catchStmt->body.as<ast::IfStmt>() ) {
     1674                        assert( ifStmt->thenPart );
     1675                }
     1676                // Encode the catchStmt so the condition can see the declaration.
    14681677                if ( catchStmt->cond ) {
    1469                         ast::ptr< ast::Type > boolType = new ast::BasicType{ ast::BasicType::Bool };
    1470                         catchStmt = ast::mutate_field(
    1471                                 catchStmt, &ast::CatchStmt::cond,
    1472                                 findSingleExpression( catchStmt->cond, boolType, symtab ) );
     1678                        ast::CatchStmt * stmt = mutate( catchStmt );
     1679                        stmt->body = new ast::IfStmt( stmt->location, stmt->cond, nullptr, stmt->body );
     1680                        stmt->cond = nullptr;
     1681                        return stmt;
     1682                }
     1683                return catchStmt;
     1684        }
     1685
     1686        const ast::CatchStmt * Resolver_new::postvisit( const ast::CatchStmt * catchStmt ) {
     1687                // Decode the catchStmt so everything is stored properly.
     1688                const ast::IfStmt * ifStmt = catchStmt->body.as<ast::IfStmt>();
     1689                if ( nullptr != ifStmt && nullptr == ifStmt->thenPart ) {
     1690                        assert( ifStmt->cond );
     1691                        assert( ifStmt->elsePart );
     1692                        ast::CatchStmt * stmt = ast::mutate( catchStmt );
     1693                        stmt->cond = ifStmt->cond;
     1694                        stmt->body = ifStmt->elsePart;
     1695                        // ifStmt should be implicately deleted here.
     1696                        return stmt;
    14731697                }
    14741698                return catchStmt;
     
    15871811                                                                // Check if the argument matches the parameter type in the current
    15881812                                                                // scope
    1589                                                                 ast::ptr< ast::Type > paramType = (*param)->get_type();
     1813                                                                // ast::ptr< ast::Type > paramType = (*param)->get_type();
    15901814                                                                if (
    15911815                                                                        ! unify(
    1592                                                                                 arg->expr->result, paramType, resultEnv, need, have, open,
     1816                                                                                arg->expr->result, *param, resultEnv, need, have, open,
    15931817                                                                                symtab )
    15941818                                                                ) {
     
    15971821                                                                        ss << "candidate function not viable: no known conversion "
    15981822                                                                                "from '";
    1599                                                                         ast::print( ss, (*param)->get_type() );
     1823                                                                        ast::print( ss, *param );
    16001824                                                                        ss << "' to '";
    16011825                                                                        ast::print( ss, arg->expr->result );
     
    17271951        }
    17281952
     1953        const ast::WithStmt * Resolver_new::previsit( const ast::WithStmt * withStmt ) {
     1954                auto mutStmt = mutate(withStmt);
     1955                resolveWithExprs(mutStmt->exprs, stmtsToAddBefore);
     1956                return mutStmt;
     1957        }
     1958
     1959        void Resolver_new::resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd) {
     1960                for (auto & expr : exprs) {
     1961                        // only struct- and union-typed expressions are viable candidates
     1962                        expr = findKindExpression( expr, symtab, structOrUnion, "with expression" );
     1963
     1964                        // if with expression might be impure, create a temporary so that it is evaluated once
     1965                        if ( Tuples::maybeImpure( expr ) ) {
     1966                                static UniqueName tmpNamer( "_with_tmp_" );
     1967                                const CodeLocation loc = expr->location;
     1968                                auto tmp = new ast::ObjectDecl(loc, tmpNamer.newName(), expr->result, new ast::SingleInit(loc, expr ) );
     1969                                expr = new ast::VariableExpr( loc, tmp );
     1970                                stmtsToAdd.push_back( new ast::DeclStmt(loc, tmp ) );
     1971                                if ( InitTweak::isConstructable( tmp->type ) ) {
     1972                                        // generate ctor/dtor and resolve them
     1973                                        tmp->init = InitTweak::genCtorInit( loc, tmp );
     1974                                }
     1975                                // since tmp is freshly created, this should modify tmp in-place
     1976                                tmp->accept( *visitor );
     1977                        }
     1978                }
     1979        }
    17291980
    17301981
     
    18222073        }
    18232074
     2075        // suppress error on autogen functions and mark invalid autogen as deleted.
     2076        bool Resolver_new::on_error(ast::ptr<ast::Decl> & decl) {
     2077                if (auto functionDecl = decl.as<ast::FunctionDecl>()) {
     2078                        // xxx - can intrinsic gen ever fail?
     2079                        if (functionDecl->linkage == ast::Linkage::AutoGen) {
     2080                                auto mutDecl = mutate(functionDecl);
     2081                                mutDecl->isDeleted = true;
     2082                                mutDecl->stmts = nullptr;
     2083                                decl = mutDecl;
     2084                                return false;
     2085                        }
     2086                }
     2087                return true;
     2088        }
     2089
    18242090} // namespace ResolvExpr
    18252091
  • src/ResolvExpr/Resolver.h

    rbdfc032 reef8dfb  
    3535        class StmtExpr;
    3636        class SymbolTable;
     37        struct TranslationUnit;
    3738        class Type;
    3839        class TypeEnvironment;
     
    5556
    5657        /// Checks types and binds syntactic constructs to typed representations
    57         void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit );
     58        void resolve( ast::TranslationUnit& translationUnit );
    5859        /// Searches expr and returns the first DeletedExpr found, otherwise nullptr
    5960        const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr );
     
    6263        ast::ptr< ast::Expr > resolveInVoidContext(
    6364                const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env );
    64         /// Resolve `untyped` to the single expression whose candidate is the best match for the 
     65        /// Resolve `untyped` to the single expression whose candidate is the best match for the
    6566        /// given type.
    6667        ast::ptr< ast::Expr > findSingleExpression(
    6768                const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab );
     69        ast::ptr< ast::Expr > findVoidExpression(
     70                const ast::Expr * untyped, const ast::SymbolTable & symtab);
    6871        /// Resolves a constructor init expression
    69         ast::ptr< ast::Init > resolveCtorInit( 
     72        ast::ptr< ast::Init > resolveCtorInit(
    7073                const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab );
    71         /// Resolves a statement expression
    72         ast::ptr< ast::Expr > resolveStmtExpr(
     74        /// Resolves a statement expression 
     75        const ast::Expr * resolveStmtExpr(
    7376                const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab );
    7477} // namespace ResolvExpr
  • src/ResolvExpr/SatisfyAssertions.cpp

    rbdfc032 reef8dfb  
    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
     
    6969        /// Reference to a single deferred item
    7070        struct DeferRef {
    71                 const ast::DeclWithType * decl;
     71                const ast::VariableExpr * expr;
    7272                const ast::AssertionSetValue & info;
    7373                const AssnCandidate & match;
     
    7777        /// Acts like an indexed list of DeferRef
    7878        struct DeferItem {
    79                 const ast::DeclWithType * decl;
     79                const ast::VariableExpr * expr;
    8080                const ast::AssertionSetValue & info;
    8181                AssnCandidateList matches;
    8282
    8383                DeferItem(
    84                         const ast::DeclWithType * d, const ast::AssertionSetValue & i, AssnCandidateList && ms )
    85                 : decl( d ), info( i ), matches( std::move( ms ) ) {}
     84                        const ast::VariableExpr * d, const ast::AssertionSetValue & i, AssnCandidateList && ms )
     85                : expr( d ), info( i ), matches( std::move( ms ) ) {}
    8686
    8787                bool empty() const { return matches.empty(); }
     
    8989                AssnCandidateList::size_type size() const { return matches.size(); }
    9090
    91                 DeferRef operator[] ( unsigned i ) const { return { decl, info, matches[i] }; }
     91                DeferRef operator[] ( unsigned i ) const { return { expr, info, matches[i] }; }
    9292        };
    9393
     
    138138        void addToSymbolTable( const ast::AssertionSet & have, ast::SymbolTable & symtab ) {
    139139                for ( auto & i : have ) {
    140                         if ( i.second.isUsed ) { symtab.addId( i.first ); }
     140                        if ( i.second.isUsed ) { symtab.addId( i.first->var ); }
    141141                }
    142142        }
     
    144144        /// Binds a single assertion, updating satisfaction state
    145145        void bindAssertion(
    146                 const ast::DeclWithType * decl, const ast::AssertionSetValue & info, CandidateRef & cand,
     146                const ast::VariableExpr * expr, const ast::AssertionSetValue & info, CandidateRef & cand,
    147147                AssnCandidate & match, InferCache & inferred
    148148        ) {
     
    156156
    157157                // place newly-inferred assertion in proper location in cache
    158                 inferred[ info.resnSlot ][ decl->uniqueId ] = ast::ParamEntry{
    159                         candidate->uniqueId, candidate, match.adjType, decl->get_type(), varExpr };
     158                inferred[ info.resnSlot ][ expr->var->uniqueId ] = ast::ParamEntry{
     159                        candidate->uniqueId, candidate, match.adjType, expr->result, varExpr };
    160160        }
    161161
     
    167167                // find candidates that unify with the desired type
    168168                AssnCandidateList matches;
    169                 for ( const ast::SymbolTable::IdData & cdata : sat.symtab.lookupId( assn.first->name ) ) {
     169
     170                std::vector<ast::SymbolTable::IdData> candidates;
     171                auto kind = ast::SymbolTable::getSpecialFunctionKind(assn.first->var->name);
     172                if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) {
     173                        // prefilter special decls by argument type, if already known
     174                        ast::ptr<ast::Type> thisArgType = assn.first->result.strict_as<ast::PointerType>()->base
     175                                .strict_as<ast::FunctionType>()->params[0]
     176                                .strict_as<ast::ReferenceType>()->base;
     177                        sat.cand->env.apply(thisArgType);
     178
     179                        std::string otypeKey = "";
     180                        if (thisArgType.as<ast::PointerType>()) otypeKey = Mangle::Encoding::pointer;
     181                        else if (!isUnboundType(thisArgType)) otypeKey = Mangle::mangle(thisArgType, Mangle::Type | Mangle::NoGenericParams);
     182
     183                        candidates = sat.symtab.specialLookupId(kind, otypeKey);
     184                }
     185                else {
     186                        candidates = sat.symtab.lookupId(assn.first->var->name);
     187                }
     188                for ( const ast::SymbolTable::IdData & cdata : candidates ) {
    170189                        const ast::DeclWithType * candidate = cdata.id;
     190
     191                        // ignore deleted candidates.
     192                        // NOTE: this behavior is different from main resolver.
     193                        // further investigations might be needed to determine
     194                        // if we should implement the same rule here
     195                        // (i.e. error if unique best match is deleted)
     196                        if (candidate->isDeleted && candidate->linkage == ast::Linkage::AutoGen) continue;
    171197
    172198                        // build independent unification context for candidate
     
    174200                        ast::TypeEnvironment newEnv{ sat.cand->env };
    175201                        ast::OpenVarSet newOpen{ sat.cand->open };
    176                         ast::ptr< ast::Type > toType = assn.first->get_type();
     202                        ast::ptr< ast::Type > toType = assn.first->result;
    177203                        ast::ptr< ast::Type > adjType =
    178                                 renameTyVars( adjustExprType( candidate->get_type(), newEnv, sat.symtab ) );
     204                                renameTyVars( adjustExprType( candidate->get_type(), newEnv, sat.symtab ), GEN_USAGE, false );
    179205
    180206                        // only keep candidates which unify
     
    188214
    189215                                matches.emplace_back(
    190                                         cdata, adjType, std::move( newEnv ), std::move( newNeed ), std::move( have ),
     216                                        cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
    191217                                        std::move( newOpen ), crntResnSlot );
    192218                        }
     
    229255                InferMatcher( InferCache & inferred ) : inferred( inferred ) {}
    230256
    231                 const ast::Expr * postmutate( const ast::Expr * expr ) {
     257                const ast::Expr * postvisit( const ast::Expr * expr ) {
    232258                        // Skip if no slots to find
    233                         if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr;
    234 
     259                        if ( !expr->inferred.hasSlots() ) return expr;
     260                        // if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr;
     261                        std::vector<UniqueId> missingSlots;
    235262                        // find inferred parameters for resolution slots
    236                         ast::InferredParams newInferred;
     263                        ast::InferredParams * newInferred = new ast::InferredParams();
    237264                        for ( UniqueId slot : expr->inferred.resnSlots() ) {
    238265                                // fail if no matching assertions found
    239266                                auto it = inferred.find( slot );
    240267                                if ( it == inferred.end() ) {
    241                                         assert(!"missing assertion");
     268                                        // std::cerr << "missing assertion " << slot << std::endl;
     269                                        missingSlots.push_back(slot);
     270                                        continue;
    242271                                }
    243272
     
    245274                                for ( auto & entry : it->second ) {
    246275                                        // recurse on inferParams of resolved expressions
    247                                         entry.second.expr = postmutate( entry.second.expr );
    248                                         auto res = newInferred.emplace( entry );
     276                                        entry.second.expr = postvisit( entry.second.expr );
     277                                        auto res = newInferred->emplace( entry );
    249278                                        assert( res.second && "all assertions newly placed" );
    250279                                }
     
    252281
    253282                        ast::Expr * ret = mutate( expr );
    254                         ret->inferred.set_inferParams( std::move( newInferred ) );
     283                        ret->inferred.set_inferParams( newInferred );
     284                        if (!missingSlots.empty()) ret->inferred.resnSlots() = missingSlots;
    255285                        return ret;
    256286                }
     
    307337                                        // compute conversion cost from satisfying decl to assertion
    308338                                        cost += computeConversionCost(
    309                                                 assn.match.adjType, assn.decl->get_type(), symtab, env );
     339                                                assn.match.adjType, assn.expr->result, false, symtab, env );
    310340
    311341                                        // mark vars+specialization on function-type assertions
     
    314344                                        if ( ! func ) continue;
    315345
    316                                         for ( const ast::DeclWithType * param : func->params ) {
    317                                                 cost.decSpec( specCost( param->get_type() ) );
     346                                        for ( const auto & param : func->params ) {
     347                                                cost.decSpec( specCost( param ) );
    318348                                        }
    319349
    320350                                        cost.incVar( func->forall.size() );
    321351
    322                                         for ( const ast::TypeDecl * td : func->forall ) {
    323                                                 cost.decSpec( td->assertions.size() );
    324                                         }
     352                                        cost.decSpec( func->assertions.size() );
    325353                                }
    326354                        }
     
    357385
    358386        /// Limit to depth of recursion of assertion satisfaction
    359         static const int recursionLimit = 7;
     387        static const int recursionLimit = 8;
    360388        /// Maximum number of simultaneously-deferred assertions to attempt concurrent satisfaction of
    361389        static const int deferLimit = 10;
     
    389417                        if ( it != thresholds.end() && it->second < sat.costs ) goto nextSat;
    390418
    391                         // make initial pass at matching assertions
    392                         for ( auto & assn : sat.need ) {
    393                                 // fail early if any assertion is not satisfiable
    394                                 if ( ! satisfyAssertion( assn, sat ) ) {
     419                        // should a limit be imposed? worst case here is O(n^2) but very unlikely to happen.
     420                        for (unsigned resetCount = 0; ; ++resetCount) {
     421                                ast::AssertionList next;
     422                                resetTyVarRenaming();
     423                                // make initial pass at matching assertions
     424                                for ( auto & assn : sat.need ) {
     425                                        // fail early if any assertion is not satisfiable
     426                                        if ( ! satisfyAssertion( assn, sat ) ) {
     427                                                next.emplace_back(assn);
     428                                                // goto nextSat;
     429                                        }
     430                                }
     431                                // success
     432                                if (next.empty()) break;
     433                                // fail if nothing resolves
     434                                else if (next.size() == sat.need.size()) {
    395435                                        Indenter tabs{ 3 };
    396436                                        std::ostringstream ss;
     
    398438                                        print( ss, *sat.cand, ++tabs );
    399439                                        ss << (tabs-1) << "Could not satisfy assertion:\n";
    400                                         ast::print( ss, assn.first, tabs );
     440                                        ast::print( ss, next[0].first, tabs );
    401441
    402442                                        errors.emplace_back( ss.str() );
    403443                                        goto nextSat;
    404444                                }
     445                                sat.need = std::move(next);
    405446                        }
    406447
     
    421462                                ss << (tabs-1) << "Too many non-unique satisfying assignments for assertions:\n";
    422463                                for ( const auto & d : sat.deferred ) {
    423                                         ast::print( ss, d.decl, tabs );
     464                                        ast::print( ss, d.expr, tabs );
    424465                                }
    425466
     
    439480                                        ss << (tabs-1) << "No mutually-compatible satisfaction for assertions:\n";
    440481                                        for ( const auto& d : sat.deferred ) {
    441                                                 ast::print( ss, d.decl, tabs );
     482                                                ast::print( ss, d.expr, tabs );
    442483                                        }
    443484
     
    471512                                                nextNewNeed.insert( match.need.begin(), match.need.end() );
    472513
    473                                                 bindAssertion( r.decl, r.info, nextCand, match, nextInferred );
     514                                                bindAssertion( r.expr, r.info, nextCand, match, nextInferred );
    474515                                        }
    475516
  • src/ResolvExpr/SatisfyAssertions.hpp

    rbdfc032 reef8dfb  
    2727namespace ResolvExpr {
    2828
    29 /// Recursively satisfies all assertions provided in a candidate; returns true if succeeds
    30 void satisfyAssertions(
    31         CandidateRef & cand, const ast::SymbolTable & symtab, CandidateList & out,
     29/// Recursively satisfies all assertions provided in a candidate
     30/// returns true if it has been run (candidate has any assertions)
     31void satisfyAssertions(
     32        CandidateRef & cand, const ast::SymbolTable & symtab, CandidateList & out,
    3233        std::vector<std::string> & errors );
    3334
  • src/ResolvExpr/SpecCost.cc

    rbdfc032 reef8dfb  
    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                        }
     
    169178                void previsit( const ast::FunctionType * fty ) {
    170179                        int minCount = std::numeric_limits<int>::max();
    171                         updateMinimumPresent( minCount, fty->params, decl_type );
    172                         updateMinimumPresent( minCount, fty->returns, decl_type );
     180                        updateMinimumPresent( minCount, fty->params, type_deref );
     181                        updateMinimumPresent( minCount, fty->returns, type_deref );
    173182                        // Add another level to minCount if set.
    174183                        count = toNoneOrInc( minCount );
     
    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/TypeEnvironment.cc

    rbdfc032 reef8dfb  
    2020#include <utility>                     // for pair, move
    2121
     22#include "CompilationState.h"          // for deterministic_output
    2223#include "Common/utility.h"            // for maybeClone
    2324#include "SynTree/Type.h"              // for Type, FunctionType, Type::Fora...
     
    106107
    107108        void EqvClass::print( std::ostream &os, Indenter indent ) const {
    108                 os << "( ";
    109                 std::copy( vars.begin(), vars.end(), std::ostream_iterator< std::string >( os, " " ) );
     109                os << "(";
     110                bool first = true;
     111                for(const auto & var : vars) {
     112                        if(first) first = false;
     113                        else os << " ";
     114                        if( deterministic_output && isUnboundType(var) ) os << "[unbound]";
     115                        else os << var;
     116                }
    110117                os << ")";
    111118                if ( type ) {
     
    235242                // check safely bindable
    236243                if ( r.type && occursIn( r.type, s.vars.begin(), s.vars.end(), *this ) ) return false;
    237                
     244
    238245                // merge classes in
    239246                r.vars.insert( s.vars.begin(), s.vars.end() );
  • src/ResolvExpr/TypeEnvironment.h

    rbdfc032 reef8dfb  
    149149                iterator end() const { return env.end(); }
    150150
     151                auto size() const { return env.size(); }
     152
    151153          private:
    152154                ClassList env;
  • src/ResolvExpr/Unify.cc

    rbdfc032 reef8dfb  
    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
     
    402395
    403396        template< typename Iterator1, typename Iterator2 >
    404         bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
     397        bool unifyTypeList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    405398                auto get_type = [](DeclarationWithType * dwt){ return dwt->get_type(); };
    406399                for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
     
    496489                                        || flatOther->isTtype()
    497490                        ) {
    498                                 if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    499                                         if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     491                                if ( unifyTypeList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     492                                        if ( unifyTypeList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    500493
    501494                                                // the original types must be used in mark assertions, since pointer comparisons are used
     
    709702                const ast::SymbolTable & symtab;
    710703        public:
     704                static size_t traceId;
    711705                bool result;
    712706
     
    773767                /// If this isn't done when satifying ttype assertions, then argument lists can have
    774768                /// different size and structure when they should be compatible.
    775                 struct TtypeExpander_new : public ast::WithShortCircuiting {
     769                struct TtypeExpander_new : public ast::WithShortCircuiting, public ast::PureVisitor {
    776770                        ast::TypeEnvironment & tenv;
    777771
     
    779773
    780774                        const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
    781                                 if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) {
     775                                if ( const ast::EqvClass * clz = tenv.lookup( *typeInst ) ) {
    782776                                        // expand ttype parameter into its actual type
    783777                                        if ( clz->data.kind == ast::TypeDecl::Ttype && clz->bound ) {
     
    790784
    791785                /// returns flattened version of `src`
    792                 static std::vector< ast::ptr< ast::DeclWithType > > flattenList(
    793                         const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env
     786                static std::vector< ast::ptr< ast::Type > > flattenList(
     787                        const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
    794788                ) {
    795                         std::vector< ast::ptr< ast::DeclWithType > > dst;
     789                        std::vector< ast::ptr< ast::Type > > dst;
    796790                        dst.reserve( src.size() );
    797                         for ( const ast::DeclWithType * d : src ) {
     791                        for ( const auto & d : src ) {
    798792                                ast::Pass<TtypeExpander_new> expander{ env };
    799                                 d = d->accept( expander );
    800                                 auto types = flatten( d->get_type() );
     793                                // TtypeExpander pass is impure (may mutate nodes in place)
     794                                // need to make nodes shared to prevent accidental mutation
     795                                ast::ptr<ast::Type> dc = d->accept(expander);
     796                                auto types = flatten( dc );
    801797                                for ( ast::ptr< ast::Type > & t : types ) {
    802798                                        // outermost const, volatile, _Atomic qualifiers in parameters should not play
     
    807803                                        // requirements than a non-mutex function
    808804                                        remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
    809                                         dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } );
     805                                        dst.emplace_back( t );
    810806                                }
    811807                        }
     
    815811                /// Creates a tuple type based on a list of DeclWithType
    816812                template< typename Iter >
    817                 static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) {
     813                static const ast::Type * tupleFromTypes( Iter crnt, Iter end ) {
    818814                        std::vector< ast::ptr< ast::Type > > types;
    819815                        while ( crnt != end ) {
    820816                                // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
    821817                                // that this results in a flat tuple
    822                                 flatten( (*crnt)->get_type(), types );
     818                                flatten( *crnt, types );
    823819
    824820                                ++crnt;
    825821                        }
    826822
    827                         return { new ast::TupleType{ std::move(types) } };
     823                        return new ast::TupleType{ std::move(types) };
    828824                }
    829825
    830826                template< typename Iter >
    831                 static bool unifyDeclList(
     827                static bool unifyTypeList(
    832828                        Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env,
    833829                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     
    835831                ) {
    836832                        while ( crnt1 != end1 && crnt2 != end2 ) {
    837                                 const ast::Type * t1 = (*crnt1)->get_type();
    838                                 const ast::Type * t2 = (*crnt2)->get_type();
     833                                const ast::Type * t1 = *crnt1;
     834                                const ast::Type * t2 = *crnt2;
    839835                                bool isTuple1 = Tuples::isTtype( t1 );
    840836                                bool isTuple2 = Tuples::isTtype( t2 );
     
    844840                                        // combine remainder of list2, then unify
    845841                                        return unifyExact(
    846                                                 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
     842                                                t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
    847843                                                noWiden(), symtab );
    848844                                } else if ( ! isTuple1 && isTuple2 ) {
    849845                                        // combine remainder of list1, then unify
    850846                                        return unifyExact(
    851                                                 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
     847                                                tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
    852848                                                noWiden(), symtab );
    853849                                }
     
    864860                        if ( crnt1 != end1 ) {
    865861                                // try unifying empty tuple with ttype
    866                                 const ast::Type * t1 = (*crnt1)->get_type();
     862                                const ast::Type * t1 = *crnt1;
    867863                                if ( ! Tuples::isTtype( t1 ) ) return false;
    868864                                return unifyExact(
    869                                         t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
     865                                        t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
    870866                                        noWiden(), symtab );
    871867                        } else if ( crnt2 != end2 ) {
    872868                                // try unifying empty tuple with ttype
    873                                 const ast::Type * t2 = (*crnt2)->get_type();
     869                                const ast::Type * t2 = *crnt2;
    874870                                if ( ! Tuples::isTtype( t2 ) ) return false;
    875871                                return unifyExact(
    876                                         tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
     872                                        tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
    877873                                        noWiden(), symtab );
    878874                        }
     
    881877                }
    882878
    883                 static bool unifyDeclList(
    884                         const std::vector< ast::ptr< ast::DeclWithType > > & list1,
    885                         const std::vector< ast::ptr< ast::DeclWithType > > & list2,
     879                static bool unifyTypeList(
     880                        const std::vector< ast::ptr< ast::Type > > & list1,
     881                        const std::vector< ast::ptr< ast::Type > > & list2,
    886882                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    887883                        const ast::OpenVarSet & open, const ast::SymbolTable & symtab
    888884                ) {
    889                         return unifyDeclList(
     885                        return unifyTypeList(
    890886                                list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,
    891887                                symtab );
    892888                }
    893889
    894                 static void markAssertionSet( ast::AssertionSet & assns, const ast::DeclWithType * assn ) {
     890                static void markAssertionSet( ast::AssertionSet & assns, const ast::VariableExpr * assn ) {
    895891                        auto i = assns.find( assn );
    896892                        if ( i != assns.end() ) {
     
    902898                static void markAssertions(
    903899                        ast::AssertionSet & assn1, ast::AssertionSet & assn2,
    904                         const ast::ParameterizedType * type
     900                        const ast::FunctionType * type
    905901                ) {
    906                         for ( const auto & tyvar : type->forall ) {
    907                                 for ( const ast::DeclWithType * assert : tyvar->assertions ) {
    908                                         markAssertionSet( assn1, assert );
    909                                         markAssertionSet( assn2, assert );
    910                                 }
     902                        for ( auto & assert : type->assertions ) {
     903                                markAssertionSet( assn1, assert );
     904                                markAssertionSet( assn2, assert );
    911905                        }
    912906                }
     
    932926                        ) return;
    933927
    934                         if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return;
    935                         if ( ! unifyDeclList(
     928                        if ( ! unifyTypeList( params, params2, tenv, need, have, open, symtab ) ) return;
     929                        if ( ! unifyTypeList(
    936930                                func->returns, func2->returns, tenv, need, have, open, symtab ) ) return;
    937931
     
    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();
     
    10321028
    10331029                void postvisit( const ast::TypeInstType * typeInst ) {
    1034                         assert( open.find( typeInst->name ) == open.end() );
     1030                        assert( open.find( *typeInst ) == open.end() );
    10351031                        handleRefType( typeInst, type2 );
    10361032                }
     
    10381034        private:
    10391035                /// Creates a tuple type based on a list of Type
    1040                 static ast::ptr< ast::Type > tupleFromTypes(
     1036                static const ast::Type * tupleFromTypes(
    10411037                        const std::vector< ast::ptr< ast::Type > > & tys
    10421038                ) {
     
    11141110
    11151111                        ast::Pass<TtypeExpander_new> expander{ tenv };
     1112
    11161113                        const ast::Type * flat = tuple->accept( expander );
    11171114                        const ast::Type * flat2 = tuple2->accept( expander );
     
    11401137        };
    11411138
     1139        // size_t Unify_new::traceId = Stats::Heap::new_stacktrace_id("Unify_new");
    11421140        bool unify(
    11431141                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     
    11711169                auto var2 = dynamic_cast< const ast::TypeInstType * >( type2 );
    11721170                ast::OpenVarSet::const_iterator
    1173                         entry1 = var1 ? open.find( var1->name ) : open.end(),
    1174                         entry2 = var2 ? open.find( var2->name ) : open.end();
     1171                        entry1 = var1 ? open.find( *var1 ) : open.end(),
     1172                        entry2 = var2 ? open.find( *var2 ) : open.end();
    11751173                bool isopen1 = entry1 != open.end();
    11761174                bool isopen2 = entry2 != open.end();
     
    11881186                        ast::Pass<Unify_new> comparator{ type2, env, need, have, open, widen, symtab };
    11891187                        type1->accept( comparator );
    1190                         return comparator.pass.result;
     1188                        return comparator.core.result;
    11911189                }
    11921190        }
     
    12021200                // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and
    12031201                // 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 );
     1202                ast::Type * t1 = shallowCopy(type1.get());
     1203                ast::Type * t2 = shallowCopy(type2.get());
     1204                t1->qualifiers = {};
     1205                t2->qualifiers = {};
     1206                ast::ptr< ast::Type > t1_(t1);
     1207                ast::ptr< ast::Type > t2_(t2);
    12071208
    12081209                if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
    1209                         t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
    1210 
    12111210                        // if exact unification on unqualified types, try to merge qualifiers
    12121211                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
    1213                                 common = type1;
    1214                                 reset_qualifiers( common, q1 | q2 );
     1212                                t1->qualifiers = q1 | q2;
     1213                                common = t1;
    12151214                                return true;
    12161215                        } else {
     
    12191218
    12201219                } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {
    1221                         t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
    1222 
    12231220                        // no exact unification, but common type
    1224                         reset_qualifiers( common, q1 | q2 );
     1221                        auto c = shallowCopy(common.get());
     1222                        c->qualifiers = q1 | q2;
     1223                        common = c;
    12251224                        return true;
    12261225                } else {
     
    12311230        ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ) {
    12321231                if ( func->returns.empty() ) return new ast::VoidType{};
    1233                 if ( func->returns.size() == 1 ) return func->returns[0]->get_type();
     1232                if ( func->returns.size() == 1 ) return func->returns[0];
    12341233
    12351234                std::vector<ast::ptr<ast::Type>> tys;
    1236                 for ( const ast::DeclWithType * decl : func->returns ) {
    1237                         tys.emplace_back( decl->get_type() );
     1235                for ( const auto & decl : func->returns ) {
     1236                        tys.emplace_back( decl );
    12381237                }
    12391238                return new ast::TupleType{ std::move(tys) };
  • src/ResolvExpr/module.mk

    rbdfc032 reef8dfb  
    1919      ResolvExpr/Alternative.cc \
    2020      ResolvExpr/AlternativeFinder.cc \
     21      ResolvExpr/AlternativeFinder.h \
     22      ResolvExpr/Alternative.h \
    2123      ResolvExpr/Candidate.cpp \
    2224      ResolvExpr/CandidateFinder.cpp \
     25      ResolvExpr/CandidateFinder.hpp \
     26      ResolvExpr/Candidate.hpp \
    2327      ResolvExpr/CastCost.cc \
    2428      ResolvExpr/CommonType.cc \
    2529      ResolvExpr/ConversionCost.cc \
     30      ResolvExpr/ConversionCost.h \
     31      ResolvExpr/Cost.h \
    2632      ResolvExpr/CurrentObject.cc \
     33      ResolvExpr/CurrentObject.h \
    2734      ResolvExpr/ExplodedActual.cc \
     35      ResolvExpr/ExplodedActual.h \
    2836      ResolvExpr/ExplodedArg.cpp \
     37      ResolvExpr/ExplodedArg.hpp \
    2938      ResolvExpr/FindOpenVars.cc \
     39      ResolvExpr/FindOpenVars.h \
    3040      ResolvExpr/Occurs.cc \
    3141      ResolvExpr/PolyCost.cc \
     
    3343      ResolvExpr/PtrsCastable.cc \
    3444      ResolvExpr/RenameVars.cc \
     45      ResolvExpr/RenameVars.h \
    3546      ResolvExpr/ResolveAssertions.cc \
     47      ResolvExpr/ResolveAssertions.h \
    3648      ResolvExpr/Resolver.cc \
     49      ResolvExpr/Resolver.h \
    3750      ResolvExpr/ResolveTypeof.cc \
     51      ResolvExpr/ResolveTypeof.h \
     52      ResolvExpr/ResolvMode.h \
    3853      ResolvExpr/SatisfyAssertions.cpp \
     54      ResolvExpr/SatisfyAssertions.hpp \
    3955      ResolvExpr/SpecCost.cc \
    4056      ResolvExpr/TypeEnvironment.cc \
    41       ResolvExpr/Unify.cc
     57      ResolvExpr/TypeEnvironment.h \
     58      ResolvExpr/typeops.h \
     59      ResolvExpr/Unify.cc \
     60      ResolvExpr/Unify.h \
     61      ResolvExpr/WidenMode.h
    4262
    43 SRC += $(SRC_RESOLVEXPR) ResolvExpr/AlternativePrinter.cc
     63
     64SRC += $(SRC_RESOLVEXPR) ResolvExpr/AlternativePrinter.cc ResolvExpr/AlternativePrinter.h
    4465SRCDEMANGLE += $(SRC_RESOLVEXPR)
  • src/ResolvExpr/typeops.h

    rbdfc032 reef8dfb  
    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.