Changeset 2890212


Ignore:
Timestamp:
Jul 31, 2019, 3:23:04 PM (2 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
arm-eh, jacob/cs343-translation, master, new-ast, new-ast-unique-expr
Children:
ae265b5, f49b3fc
Parents:
504eb72
Message:

Startup.cfa now compiles with new ast

Location:
src
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Expr.cpp

    r504eb72 r2890212  
    2020#include <vector>
    2121
     22#include "Copy.hpp"                // for shallowCopy
    2223#include "Eval.hpp"                // for call
    2324#include "GenericSubstitution.hpp"
     
    174175        assert( var );
    175176        assert( var->get_type() );
    176         result = var->get_type();
    177         add_qualifiers( result, CV::Lvalue );
     177        auto r = shallowCopy( var->get_type() );
     178        r->qualifiers |= CV::Lvalue;
     179        result = r;
    178180}
    179181
  • src/AST/Node.hpp

    r504eb72 r2890212  
    9696        assertf(
    9797                node->weak_count == 0,
    98                 "Error: mutating node with weak references to it will invalided some references"
     98                "Error: mutating node with weak references to it will invalidate some references"
    9999        );
    100100        return node->clone();
     
    106106        // skip mutate if equivalent
    107107        if ( node->*field == val ) return node;
    108        
     108
    109109        // mutate and return
    110110        node_t * ret = mutate( node );
  • src/AST/TypeEnvironment.hpp

    r504eb72 r2890212  
    3838/// Adding this comparison operator significantly improves assertion satisfaction run time for
    3939/// some cases. The current satisfaction algorithm's speed partially depends on the order of
    40 /// assertions. Assertions which have fewer possible matches should appear before assertions 
    41 /// which have more possible matches. This seems to imply that this could be further improved 
    42 /// by providing an indexer as an additional argument and ordering based on the number of 
     40/// assertions. Assertions which have fewer possible matches should appear before assertions
     41/// which have more possible matches. This seems to imply that this could be further improved
     42/// by providing an indexer as an additional argument and ordering based on the number of
    4343/// matches of the same kind (object, function) for the names of the declarations.
    4444///
    45 /// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this 
     45/// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this
    4646/// comparator.
    4747///
    48 /// Note: since this compares pointers for position, minor changes in the source file that 
    49 /// affect memory layout can alter compilation time in unpredictable ways. For example, the 
    50 /// placement of a line directive can reorder type pointers with respect to each other so that 
    51 /// assertions are seen in different orders, causing a potentially different number of 
    52 /// unification calls when resolving assertions. I've seen a TU go from 36 seconds to 27 
    53 /// seconds by reordering line directives alone, so it would be nice to fix this comparison so 
    54 /// that assertions compare more consistently. I've tried to modify this to compare on mangle 
    55 /// name instead of type as the second comparator, but this causes some assertions to never be 
     48/// Note: since this compares pointers for position, minor changes in the source file that
     49/// affect memory layout can alter compilation time in unpredictable ways. For example, the
     50/// placement of a line directive can reorder type pointers with respect to each other so that
     51/// assertions are seen in different orders, causing a potentially different number of
     52/// unification calls when resolving assertions. I've seen a TU go from 36 seconds to 27
     53/// seconds by reordering line directives alone, so it would be nice to fix this comparison so
     54/// that assertions compare more consistently. I've tried to modify this to compare on mangle
     55/// name instead of type as the second comparator, but this causes some assertions to never be
    5656/// recorded. More investigation is needed.
    5757struct AssertCompare {
     
    8787void print( std::ostream &, const OpenVarSet &, Indenter indent = {} );
    8888
    89 /// Represents an equivalence class of bound type variables, optionally with the concrete type 
     89/// Represents an equivalence class of bound type variables, optionally with the concrete type
    9090/// they bind to.
    9191struct EqvClass {
     
    9696
    9797        EqvClass() : vars(), bound(), allowWidening( true ), data() {}
    98        
     98
    9999        /// Copy-with-bound constructor
    100         EqvClass( const EqvClass & o, const Type * b ) 
     100        EqvClass( const EqvClass & o, const Type * b )
    101101        : vars( o.vars ), bound( b ), allowWidening( o.allowWidening ), data( o.data ) {}
    102102
     
    143143        void writeToSubstitution( TypeSubstitution & sub ) const;
    144144
    145         template< typename node_t, enum Node::ref_type ref_t >
    146         int apply( ptr_base< node_t, ref_t > & type ) const {
     145        template< typename node_t >
     146        auto apply( node_t && type ) const {
    147147                TypeSubstitution sub;
    148148                writeToSubstitution( sub );
    149                 return sub.apply( type );
    150         }
    151 
    152         template< typename node_t, enum Node::ref_type ref_t >
    153         int applyFree( ptr_base< node_t, ref_t > & type ) const {
     149                return sub.apply( std::forward<node_t>(type) );
     150        }
     151
     152        template< typename node_t >
     153        auto applyFree( node_t && type ) const {
    154154                TypeSubstitution sub;
    155155                writeToSubstitution( sub );
    156                 return sub.applyFree( type );
     156                return sub.applyFree( std::forward<node_t>(type) );
    157157        }
    158158
     
    173173        void addActual( const TypeEnvironment & actualEnv, OpenVarSet & openVars );
    174174
    175         /// Binds the type class represented by `typeInst` to the type `bindTo`; will add the class if 
     175        /// Binds the type class represented by `typeInst` to the type `bindTo`; will add the class if
    176176        /// needed. Returns false on failure.
    177         bool bindVar( 
    178                 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 
    179                 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 
     177        bool bindVar(
     178                const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data,
     179                AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars,
    180180                ResolvExpr::WidenMode widen, const SymbolTable & symtab );
    181        
    182         /// Binds the type classes represented by `var1` and `var2` together; will add one or both 
     181
     182        /// Binds the type classes represented by `var1` and `var2` together; will add one or both
    183183        /// classes if needed. Returns false on failure.
    184         bool bindVarToVar( 
    185                 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 
    186                 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 
     184        bool bindVarToVar(
     185                const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data,
     186                AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars,
    187187                ResolvExpr::WidenMode widen, const SymbolTable & symtab );
    188188
     
    199199
    200200        /// Unifies the type bound of `to` with the type bound of `from`, returning false if fails
    201         bool mergeBound( 
     201        bool mergeBound(
    202202                EqvClass & to, const EqvClass & from, OpenVarSet & openVars, const SymbolTable & symtab );
    203203
    204204        /// Merges two type classes from local environment, returning false if fails
    205         bool mergeClasses( 
    206                 ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars, 
     205        bool mergeClasses(
     206                ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars,
    207207                const SymbolTable & symtab );
    208208
  • src/AST/TypeSubstitution.cpp

    r504eb72 r2890212  
    146146                ptr<Type> newType = i->second; // force clone if needed
    147147                add_qualifiers( newType, inst->qualifiers );
    148                 // Note: need to recursively apply substitution to the new type because normalize does not 
     148                // Note: need to recursively apply substitution to the new type because normalize does not
    149149                // substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
    150150                newType = newType->accept( *visitor );
     
    159159        } else {
    160160                subCount++;
    161                 delete nameExpr;
    162161                return i->second;
    163162        } // if
  • src/AST/TypeSubstitution.hpp

    r504eb72 r2890212  
    4444        TypeSubstitution &operator=( const TypeSubstitution &other );
    4545
    46         template< typename SynTreeClass > int apply( const SynTreeClass *& input ) const;
    47         template< typename SynTreeClass > int applyFree( const SynTreeClass *& input ) const;
     46        template< typename SynTreeClass >
     47        struct ApplyResult {
     48                const SynTreeClass * node;
     49                int count;
     50        };
     51
     52        template< typename SynTreeClass > ApplyResult<SynTreeClass> apply( const SynTreeClass * input ) const;
     53        template< typename SynTreeClass > ApplyResult<SynTreeClass> applyFree( const SynTreeClass * input ) const;
    4854
    4955        template< typename node_t, enum Node::ref_type ref_t >
    5056        int apply( ptr_base< node_t, ref_t > & input ) const {
    5157                const node_t * p = input.get();
    52                 int ret = apply(p);
    53                 input = p;
    54                 return ret;
     58                auto ret = apply(p);
     59                input = ret.node;
     60                return ret.count;
    5561        }
    5662
     
    5864        int applyFree( ptr_base< node_t, ref_t > & input ) const {
    5965                const node_t * p = input.get();
    60                 int ret = applyFree(p);
    61                 input = p;
    62                 return ret;
     66                auto ret = applyFree(p);
     67                input = ret.node;
     68                return ret.count;
    6369        }
    6470
     
    175181
    176182template< typename SynTreeClass >
    177 int TypeSubstitution::apply( const SynTreeClass *& input ) const {
     183TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::apply( const SynTreeClass * input ) const {
    178184        assert( input );
    179185        Pass<Substituter> sub( *this, false );
    180186        input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
    181 ///     std::cerr << "substitution result is: ";
    182 ///     newType->print( std::cerr );
    183 ///     std::cerr << std::endl;
    184         return sub.pass.subCount;
     187        return { input, sub.pass.subCount };
    185188}
    186189
    187190template< typename SynTreeClass >
    188 int TypeSubstitution::applyFree( const SynTreeClass *& input ) const {
     191TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::applyFree( const SynTreeClass * input ) const {
    189192        assert( input );
    190193        Pass<Substituter> sub( *this, true );
    191194        input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
    192 ///     std::cerr << "substitution result is: ";
    193 ///     newType->print( std::cerr );
    194 ///     std::cerr << std::endl;
    195         return sub.pass.subCount;
     195        return { input, sub.pass.subCount };
    196196}
    197197
  • src/ResolvExpr/CandidateFinder.cpp

    r504eb72 r2890212  
    5454                return new ast::CastExpr{ expr, expr->result->stripReferences() };
    5555        }
    56        
     56
    5757        return expr;
    5858}
     
    6161UniqueId globalResnSlot = 0;
    6262
    63 Cost computeConversionCost( 
    64         const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab, 
    65         const ast::TypeEnvironment & env 
     63Cost computeConversionCost(
     64        const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab,
     65        const ast::TypeEnvironment & env
    6666) {
    6767        PRINT(
     
    107107
    108108        /// Computes conversion cost for a given expression to a given type
    109         const ast::Expr * computeExpressionConversionCost( 
    110                 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 
     109        const ast::Expr * computeExpressionConversionCost(
     110                const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost
    111111        ) {
    112112                Cost convCost = computeConversionCost( arg->result, paramType, symtab, env );
    113113                outCost += convCost;
    114114
    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 
     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
    117117                // infer parameters and this does not currently work for the reason stated below
    118118                Cost tmpCost = convCost;
     
    123123                        return new ast::CastExpr{ arg, newType };
    124124
    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, 
     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,
    127127                        // 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 
     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
    130130                        // commontype(zero_t, DT*) is DT*, rather than nothing
    131131
    132132                        // CandidateFinder finder{ symtab, env };
    133133                        // finder.find( arg, ResolvMode::withAdjustment() );
    134                         // assertf( finder.candidates.size() > 0, 
     134                        // assertf( finder.candidates.size() > 0,
    135135                        //      "Somehow castable expression failed to find alternatives." );
    136                         // assertf( finder.candidates.size() == 1, 
     136                        // assertf( finder.candidates.size() == 1,
    137137                        //      "Somehow got multiple alternatives for known cast expression." );
    138138                        // return finder.candidates.front()->expr;
     
    143143
    144144        /// Computes conversion cost for a given candidate
    145         Cost computeApplicationConversionCost( 
    146                 CandidateRef cand, const ast::SymbolTable & symtab 
     145        Cost computeApplicationConversionCost(
     146                CandidateRef cand, const ast::SymbolTable & symtab
    147147        ) {
    148148                auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >();
     
    167167                                if ( function->isVarArgs ) {
    168168                                        convCost.incUnsafe();
    169                                         PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 
     169                                        PRINT( std::cerr << "end of params with varargs function: inc unsafe: "
    170170                                                << convCost << std::endl; ; )
    171171                                        // convert reference-typed expressions into value-typed expressions
    172                                         cand->expr = ast::mutate_field_index( 
    173                                                 appExpr, &ast::ApplicationExpr::args, i, 
     172                                        cand->expr = ast::mutate_field_index(
     173                                                appExpr, &ast::ApplicationExpr::args, i,
    174174                                                referenceToRvalueConversion( args[i], convCost ) );
    175175                                        continue;
     
    180180                                // Default arguments should be free - don't include conversion cost.
    181181                                // Unwrap them here because they are not relevant to the rest of the system
    182                                 cand->expr = ast::mutate_field_index( 
     182                                cand->expr = ast::mutate_field_index(
    183183                                        appExpr, &ast::ApplicationExpr::args, i, def->expr );
    184184                                ++param;
     
    188188                        // mark conversion cost and also specialization cost of param type
    189189                        const ast::Type * paramType = (*param)->get_type();
    190                         cand->expr = ast::mutate_field_index( 
    191                                 appExpr, &ast::ApplicationExpr::args, i, 
    192                                 computeExpressionConversionCost( 
     190                        cand->expr = ast::mutate_field_index(
     191                                appExpr, &ast::ApplicationExpr::args, i,
     192                                computeExpressionConversionCost(
    193193                                        args[i], paramType, symtab, cand->env, convCost ) );
    194194                        convCost.decSpec( specCost( paramType ) );
     
    198198                if ( param != params.end() ) return Cost::infinity;
    199199
    200                 // specialization cost of return types can't be accounted for directly, it disables 
     200                // specialization cost of return types can't be accounted for directly, it disables
    201201                // otherwise-identical calls, like this example based on auto-newline in the I/O lib:
    202202                //
     
    215215        }
    216216
    217         void makeUnifiableVars( 
    218                 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars, 
    219                 ast::AssertionSet & need 
     217        void makeUnifiableVars(
     218                const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars,
     219                ast::AssertionSet & need
    220220        ) {
    221221                for ( const ast::TypeDecl * tyvar : type->forall ) {
     
    254254
    255255                ArgPack()
    256                 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 
     256                : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ),
    257257                  tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    258                
    259                 ArgPack( 
    260                         const ast::TypeEnvironment & env, const ast::AssertionSet & need, 
     258
     259                ArgPack(
     260                        const ast::TypeEnvironment & env, const ast::AssertionSet & need,
    261261                        const ast::AssertionSet & have, const ast::OpenVarSet & open )
    262                 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 
     262                : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ),
    263263                  open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    264                
     264
    265265                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, 
     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,
    269269                        unsigned nextExpl = 0, unsigned explAlt = 0 )
    270270                : parent(parent), expr( expr ), cost( cost ), env( move( env ) ), need( move( need ) ),
    271271                  have( move( have ) ), open( move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ),
    272272                  nextExpl( nextExpl ), explAlt( explAlt ) {}
    273                
     273
    274274                ArgPack(
    275                         const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 
     275                        const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need,
    276276                        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 ), 
     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 ),
    279279                  tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {}
    280                
     280
    281281                /// true if this pack is in the middle of an exploded argument
    282282                bool hasExpl() const { return nextExpl > 0; }
     
    286286                        return args[ nextArg-1 ][ explAlt ];
    287287                }
    288                
     288
    289289                /// Ends a tuple expression, consolidating the appropriate args
    290290                void endTuple( const std::vector< ArgPack > & packs ) {
     
    307307
    308308        /// 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 
     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
    313313        ) {
    314314                if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) {
     
    318318                                // xxx - dropping initializer changes behaviour from previous, but seems correct
    319319                                // ^^^ need to handle the case where a tuple has a default argument
    320                                 if ( ! instantiateArgument( 
     320                                if ( ! instantiateArgument(
    321321                                        type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;
    322322                                nTuples = 0;
     
    329329                } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) {
    330330                        // paramType is a ttype, consumes all remaining arguments
    331                        
     331
    332332                        // completed tuples; will be spliced to end of results to finish
    333333                        std::vector< ArgPack > finalResults{};
     
    342342                                for ( std::size_t i = genStart; i < genEnd; ++i ) {
    343343                                        unsigned nextArg = results[i].nextArg;
    344                                        
     344
    345345                                        // use next element of exploded tuple if present
    346346                                        if ( results[i].hasExpl() ) {
     
    352352                                                results.emplace_back(
    353353                                                        i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),
    354                                                         copy( results[i].need ), copy( results[i].have ), 
     354                                                        copy( results[i].need ), copy( results[i].have ),
    355355                                                        copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl,
    356356                                                        results[i].explAlt );
     
    398398
    399399                                                // check unification for ttype before adding to final
    400                                                 if ( 
    401                                                         unify( 
     400                                                if (
     401                                                        unify(
    402402                                                                ttype, argType, newResult.env, newResult.need, newResult.have,
    403                                                                 newResult.open, symtab ) 
     403                                                                newResult.open, symtab )
    404404                                                ) {
    405405                                                        finalResults.emplace_back( move( newResult ) );
     
    422422                                                if ( expl.exprs.empty() ) {
    423423                                                        results.emplace_back(
    424                                                                 results[i], move( env ), copy( results[i].need ), 
     424                                                                results[i], move( env ), copy( results[i].need ),
    425425                                                                copy( results[i].have ), move( open ), nextArg + 1, expl.cost );
    426                                                        
     426
    427427                                                        continue;
    428428                                                }
     
    430430                                                // add new result
    431431                                                results.emplace_back(
    432                                                         i, expl.exprs.front(), move( env ), copy( results[i].need ), 
    433                                                         copy( results[i].have ), move( open ), nextArg + 1, nTuples, 
     432                                                        i, expl.exprs.front(), move( env ), copy( results[i].need ),
     433                                                        copy( results[i].have ), move( open ), nextArg + 1, nTuples,
    434434                                                        expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    435435                                        }
     
    477477
    478478                                        results.emplace_back(
    479                                                 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 
     479                                                i, expr, move( env ), move( need ), move( have ), move( open ), nextArg,
    480480                                                nTuples, Cost::zero, nextExpl, results[i].explAlt );
    481481                                }
     
    493493                                        if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {
    494494                                                results.emplace_back(
    495                                                         i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 
     495                                                        i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ),
    496496                                                        move( need ), move( have ), move( open ), nextArg, nTuples );
    497497                                        }
     
    515515                                if ( expl.exprs.empty() ) {
    516516                                        results.emplace_back(
    517                                                 results[i], move( env ), move( need ), move( have ), move( open ), 
     517                                                results[i], move( env ), move( need ), move( have ), move( open ),
    518518                                                nextArg + 1, expl.cost );
    519                                        
     519
    520520                                        continue;
    521521                                }
     
    537537                                        // add new result
    538538                                        results.emplace_back(
    539                                                 i, expr, move( env ), move( need ), move( have ), move( open ), 
     539                                                i, expr, move( env ), move( need ), move( have ), move( open ),
    540540                                                nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    541541                                }
     
    550550
    551551        /// Generate a cast expression from `arg` to `toType`
    552         const ast::Expr * restructureCast( 
     552        const ast::Expr * restructureCast(
    553553                ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast
    554554        ) {
    555                 if ( 
    556                         arg->result->size() > 1 
    557                         && ! toType->isVoid() 
    558                         && ! dynamic_cast< const ast::ReferenceType * >( toType ) 
     555                if (
     556                        arg->result->size() > 1
     557                        && ! toType->isVoid()
     558                        && ! dynamic_cast< const ast::ReferenceType * >( toType )
    559559                ) {
    560                         // Argument is a tuple and the target type is neither void nor a reference. Cast each 
    561                         // member of the tuple to its corresponding target type, producing the tuple of those 
    562                         // cast expressions. If there are more components of the tuple than components in the 
    563                         // target type, then excess components do not come out in the result expression (but 
     560                        // Argument is a tuple and the target type is neither void nor a reference. Cast each
     561                        // member of the tuple to its corresponding target type, producing the tuple of those
     562                        // cast expressions. If there are more components of the tuple than components in the
     563                        // target type, then excess components do not come out in the result expression (but
    564564                        // UniqueExpr ensures that the side effects will still be produced)
    565565                        if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {
    566                                 // expressions which may contain side effects require a single unique instance of 
     566                                // expressions which may contain side effects require a single unique instance of
    567567                                // the expression
    568568                                arg = new ast::UniqueExpr{ arg->location, arg };
     
    572572                                // cast each component
    573573                                ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i };
    574                                 components.emplace_back( 
     574                                components.emplace_back(
    575575                                        restructureCast( idx, toType->getComponent( i ), isGenerated ) );
    576576                        }
     
    601601
    602602                Finder( CandidateFinder & f )
    603                 : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ), 
     603                : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
    604604                  targetType( f.targetType ) {}
    605                
     605
    606606                void previsit( const ast::Node * ) { visit_children = false; }
    607607
     
    638638
    639639                /// Completes a function candidate with arguments located
    640                 void validateFunctionCandidate( 
    641                         const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 
    642                         CandidateList & out 
     640                void validateFunctionCandidate(
     641                        const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,
     642                        CandidateList & out
    643643                ) {
    644                         ast::ApplicationExpr * appExpr = 
     644                        ast::ApplicationExpr * appExpr =
    645645                                new ast::ApplicationExpr{ func->expr->location, func->expr };
    646646                        // sum cost and accumulate arguments
     
    656656                        appExpr->args = move( vargs );
    657657                        // build and validate new candidate
    658                         auto newCand = 
     658                        auto newCand =
    659659                                std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );
    660660                        PRINT(
     
    668668                /// Builds a list of candidates for a function, storing them in out
    669669                void makeFunctionCandidates(
    670                         const CandidateRef & func, const ast::FunctionType * funcType, 
     670                        const CandidateRef & func, const ast::FunctionType * funcType,
    671671                        const ExplodedArgs_new & args, CandidateList & out
    672672                ) {
     
    675675                        ast::TypeEnvironment funcEnv{ func->env };
    676676                        makeUnifiableVars( funcType, funcOpen, funcNeed );
    677                         // add all type variables as open variables now so that those not used in the 
     677                        // add all type variables as open variables now so that those not used in the
    678678                        // parameter list are still considered open
    679679                        funcEnv.add( funcType->forall );
     
    682682                                // attempt to narrow based on expected target type
    683683                                const ast::Type * returnType = funcType->returns.front()->get_type();
    684                                 if ( ! unify( 
    685                                         returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 
     684                                if ( ! unify(
     685                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
    686686                                ) {
    687687                                        // unification failed, do not pursue this candidate
     
    697697                        for ( const ast::DeclWithType * param : funcType->params ) {
    698698                                auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
    699                                 // Try adding the arguments corresponding to the current parameter to the existing 
     699                                // Try adding the arguments corresponding to the current parameter to the existing
    700700                                // matches
    701                                 if ( ! instantiateArgument( 
     701                                if ( ! instantiateArgument(
    702702                                        obj->type, obj->init, args, results, genStart, symtab ) ) return;
    703703                        }
     
    749749                                                        if ( expl.exprs.empty() ) {
    750750                                                                results.emplace_back(
    751                                                                         results[i], move( env ), copy( results[i].need ), 
    752                                                                         copy( results[i].have ), move( open ), nextArg + 1, 
     751                                                                        results[i], move( env ), copy( results[i].need ),
     752                                                                        copy( results[i].have ), move( open ), nextArg + 1,
    753753                                                                        expl.cost );
    754754
     
    759759                                                        results.emplace_back(
    760760                                                                i, expl.exprs.front(), move( env ), copy( results[i].need ),
    761                                                                 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 
     761                                                                copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost,
    762762                                                                expl.exprs.size() == 1 ? 0 : 1, j );
    763763                                                }
     
    779779                /// Adds implicit struct-conversions to the alternative list
    780780                void addAnonConversions( const CandidateRef & cand ) {
    781                         // adds anonymous member interpretations whenever an aggregate value type is seen. 
    782                         // it's okay for the aggregate expression to have reference type -- cast it to the 
     781                        // adds anonymous member interpretations whenever an aggregate value type is seen.
     782                        // it's okay for the aggregate expression to have reference type -- cast it to the
    783783                        // base type to treat the aggregate as the referenced value
    784784                        ast::ptr< ast::Expr > aggrExpr( cand->expr );
    785785                        ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;
    786786                        cand->env.apply( aggrType );
    787                        
     787
    788788                        if ( aggrType.as< ast::ReferenceType >() ) {
    789789                                aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };
     
    798798
    799799                /// Adds aggregate member interpretations
    800                 void addAggMembers( 
    801                         const ast::ReferenceToType * aggrInst, const ast::Expr * expr, 
    802                         const Candidate & cand, const Cost & addedCost, const std::string & name 
     800                void addAggMembers(
     801                        const ast::ReferenceToType * aggrInst, const ast::Expr * expr,
     802                        const Candidate & cand, const Cost & addedCost, const std::string & name
    803803                ) {
    804804                        for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {
    805805                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );
    806                                 CandidateRef newCand = std::make_shared<Candidate>( 
     806                                CandidateRef newCand = std::make_shared<Candidate>(
    807807                                        cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
    808                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     808                                // add anonymous member interpretations whenever an aggregate value type is seen
    809809                                // as a member expression
    810810                                addAnonConversions( newCand );
     
    814814
    815815                /// Adds tuple member interpretations
    816                 void addTupleMembers( 
    817                         const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 
    818                         const Cost & addedCost, const ast::Expr * member 
     816                void addTupleMembers(
     817                        const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,
     818                        const Cost & addedCost, const ast::Expr * member
    819819                ) {
    820820                        if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) {
    821                                 // get the value of the constant expression as an int, must be between 0 and the 
     821                                // get the value of the constant expression as an int, must be between 0 and the
    822822                                // length of the tuple to have meaning
    823823                                long long val = constantExpr->intValue();
    824824                                if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    825825                                        addCandidate(
    826                                                 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 
     826                                                cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },
    827827                                                addedCost );
    828828                                }
     
    836836                        if ( funcFinder.candidates.empty() ) return;
    837837
    838                         std::vector< CandidateFinder > argCandidates = 
     838                        std::vector< CandidateFinder > argCandidates =
    839839                                selfFinder.findSubExprs( untypedExpr->args );
    840                        
     840
    841841                        // take care of possible tuple assignments
    842842                        // if not tuple assignment, handled as normal function call
     
    876876                                                if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    877877                                                        CandidateRef newFunc{ new Candidate{ *func } };
    878                                                         newFunc->expr = 
     878                                                        newFunc->expr =
    879879                                                                referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    880880                                                        makeFunctionCandidates( newFunc, function, argExpansions, found );
    881881                                                }
    882                                         } else if ( 
    883                                                 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 
     882                                        } else if (
     883                                                auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
    884884                                        ) {
    885885                                                if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) {
    886886                                                        if ( auto function = clz->bound.as< ast::FunctionType >() ) {
    887887                                                                CandidateRef newFunc{ new Candidate{ *func } };
    888                                                                 newFunc->expr = 
     888                                                                newFunc->expr =
    889889                                                                        referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    890890                                                                makeFunctionCandidates( newFunc, function, argExpansions, found );
     
    900900                                std::vector< ExplodedArg > funcE;
    901901                                funcE.reserve( funcFinder.candidates.size() );
    902                                 for ( const CandidateRef & func : funcFinder ) { 
     902                                for ( const CandidateRef & func : funcFinder ) {
    903903                                        funcE.emplace_back( *func, symtab );
    904904                                }
     
    912912                                                        if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    913913                                                                CandidateRef newOp{ new Candidate{ *op} };
    914                                                                 newOp->expr = 
     914                                                                newOp->expr =
    915915                                                                        referenceToRvalueConversion( newOp->expr, newOp->cost );
    916916                                                                makeFunctionCandidates( newOp, function, argExpansions, found );
     
    921921                        }
    922922
    923                         // Implement SFINAE; resolution errors are only errors if there aren't any non-error 
     923                        // Implement SFINAE; resolution errors are only errors if there aren't any non-error
    924924                        // candidates
    925925                        if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
     
    933933                                        auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
    934934                                        auto function = pointer->base.strict_as< ast::FunctionType >();
    935                                        
     935
    936936                                        std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;
    937937                                        std::cerr << "parameters are:" << std::endl;
     
    956956                        promoteCvtCost( winners );
    957957
    958                         // function may return a struct/union value, in which case we need to add candidates 
    959                         // for implicit conversions to each of the anonymous members, which must happen after 
     958                        // function may return a struct/union value, in which case we need to add candidates
     959                        // for implicit conversions to each of the anonymous members, which must happen after
    960960                        // `findMinCost`, since anon conversions are never the cheapest
    961961                        for ( const CandidateRef & c : winners ) {
     
    965965
    966966                        if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
    967                                 // If resolution is unsuccessful with a target type, try again without, since it 
     967                                // If resolution is unsuccessful with a target type, try again without, since it
    968968                                // will sometimes succeed when it wouldn't with a target type binding.
    969969                                // For example:
     
    10151015                                cand->env.extractOpenVars( open );
    10161016
    1017                                 // It is possible that a cast can throw away some values in a multiply-valued 
    1018                                 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the 
    1019                                 // subexpression results that are cast directly. The candidate is invalid if it 
     1017                                // It is possible that a cast can throw away some values in a multiply-valued
     1018                                // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the
     1019                                // subexpression results that are cast directly. The candidate is invalid if it
    10201020                                // has fewer results than there are types to cast to.
    10211021                                int discardedValues = cand->expr->result->size() - toType->size();
     
    10361036                                        // count one safe conversion for each value that is thrown away
    10371037                                        thisCost.incSafe( discardedValues );
    1038                                         CandidateRef newCand = std::make_shared<Candidate>( 
    1039                                                 restructureCast( cand->expr, toType, castExpr->isGenerated ), 
    1040                                                 copy( cand->env ), move( open ), move( need ), cand->cost, 
     1038                                        CandidateRef newCand = std::make_shared<Candidate>(
     1039                                                restructureCast( cand->expr, toType, castExpr->isGenerated ),
     1040                                                copy( cand->env ), move( open ), move( need ), cand->cost,
    10411041                                                cand->cost + thisCost );
    10421042                                        inferParameters( newCand, matches );
     
    10561056                        finder.find( castExpr->arg, ResolvMode::withoutPrune() );
    10571057                        for ( CandidateRef & r : finder.candidates ) {
    1058                                 addCandidate( 
    1059                                         *r, 
     1058                                addCandidate(
     1059                                        *r,
    10601060                                        new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
    10611061                        }
     
    10661066                        aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    10671067                        for ( CandidateRef & agg : aggFinder.candidates ) {
    1068                                 // it's okay for the aggregate expression to have reference type -- cast it to the 
     1068                                // it's okay for the aggregate expression to have reference type -- cast it to the
    10691069                                // base type to treat the aggregate as the referenced value
    10701070                                Cost addedCost = Cost::zero;
     
    10731073                                // find member of the given type
    10741074                                if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {
    1075                                         addAggMembers( 
     1075                                        addAggMembers(
    10761076                                                structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10771077                                } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {
    1078                                         addAggMembers( 
     1078                                        addAggMembers(
    10791079                                                unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10801080                                } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {
     
    10961096
    10971097                                CandidateRef newCand = std::make_shared<Candidate>(
    1098                                         newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 
     1098                                        newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
    10991099                                        cost );
    11001100                                PRINT(
     
    11061106                                        std::cerr << std::endl;
    11071107                                )
    1108                                 newCand->expr = ast::mutate_field( 
    1109                                         newCand->expr.get(), &ast::Expr::result, 
     1108                                newCand->expr = ast::mutate_field(
     1109                                        newCand->expr.get(), &ast::Expr::result,
    11101110                                        renameTyVars( newCand->expr->result ) );
    1111                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     1111                                // add anonymous member interpretations whenever an aggregate value type is seen
    11121112                                // as a name expression
    11131113                                addAnonConversions( newCand );
     
    11191119                        // not sufficient to just pass `variableExpr` here, type might have changed since
    11201120                        // creation
    1121                         addCandidate( 
     1121                        addCandidate(
    11221122                                new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
    11231123                }
     
    11291129                void postvisit( const ast::SizeofExpr * sizeofExpr ) {
    11301130                        if ( sizeofExpr->type ) {
    1131                                 addCandidate( 
    1132                                         new ast::SizeofExpr{ 
    1133                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 
     1131                                addCandidate(
     1132                                        new ast::SizeofExpr{
     1133                                                sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
    11341134                                        tenv );
    11351135                        } else {
     
    11401140                                CandidateList winners = findMinCost( finder.candidates );
    11411141                                if ( winners.size() != 1 ) {
    1142                                         SemanticError( 
     1142                                        SemanticError(
    11431143                                                sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );
    11441144                                }
     
    11531153                void postvisit( const ast::AlignofExpr * alignofExpr ) {
    11541154                        if ( alignofExpr->type ) {
    1155                                 addCandidate( 
    1156                                         new ast::AlignofExpr{ 
    1157                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 
     1155                                addCandidate(
     1156                                        new ast::AlignofExpr{
     1157                                                alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
    11581158                                        tenv );
    11591159                        } else {
     
    11641164                                CandidateList winners = findMinCost( finder.candidates );
    11651165                                if ( winners.size() != 1 ) {
    1166                                         SemanticError( 
     1166                                        SemanticError(
    11671167                                                alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );
    11681168                                }
     
    11711171                                choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    11721172                                choice->cost = Cost::zero;
    1173                                 addCandidate( 
     1173                                addCandidate(
    11741174                                        *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );
    11751175                        }
     
    11841184                        for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {
    11851185                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );
    1186                                 addCandidate( 
     1186                                addCandidate(
    11871187                                        new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );
    11881188                        }
     
    12171217
    12181218                                        addCandidate(
    1219                                                 new ast::LogicalExpr{ 
     1219                                                new ast::LogicalExpr{
    12201220                                                        logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
    12211221                                                move( env ), move( open ), move( need ), r1->cost + r2->cost );
     
    12551255                                                ast::AssertionSet have;
    12561256
    1257                                                 // unify true and false results, then infer parameters to produce new 
     1257                                                // unify true and false results, then infer parameters to produce new
    12581258                                                // candidates
    12591259                                                ast::ptr< ast::Type > common;
    1260                                                 if ( 
    1261                                                         unify( 
    1262                                                                 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 
    1263                                                                 common ) 
     1260                                                if (
     1261                                                        unify(
     1262                                                                r2->expr->result, r3->expr->result, env, need, have, open, symtab,
     1263                                                                common )
    12641264                                                ) {
    12651265                                                        // generate typed expression
    1266                                                         ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 
     1266                                                        ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{
    12671267                                                                conditionalExpr->location, r1->expr, r2->expr, r3->expr };
    12681268                                                        newExpr->result = common ? common : r2->expr->result;
    12691269                                                        // convert both options to result type
    12701270                                                        Cost cost = r1->cost + r2->cost + r3->cost;
    1271                                                         newExpr->arg2 = computeExpressionConversionCost( 
     1271                                                        newExpr->arg2 = computeExpressionConversionCost(
    12721272                                                                newExpr->arg2, newExpr->result, symtab, env, cost );
    12731273                                                        newExpr->arg3 = computeExpressionConversionCost(
     
    12861286                        ast::TypeEnvironment env{ tenv };
    12871287                        ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
    1288                        
     1288
    12891289                        CandidateFinder finder2{ symtab, env };
    12901290                        finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
     
    13291329
    13301330                                        ast::ptr< ast::Type > common;
    1331                                         if ( 
    1332                                                 unify( 
    1333                                                         r1->expr->result, r2->expr->result, env, need, have, open, symtab, 
    1334                                                         common ) 
     1331                                        if (
     1332                                                unify(
     1333                                                        r1->expr->result, r2->expr->result, env, need, have, open, symtab,
     1334                                                        common )
    13351335                                        ) {
    13361336                                                // generate new expression
    1337                                                 ast::RangeExpr * newExpr = 
     1337                                                ast::RangeExpr * newExpr =
    13381338                                                        new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
    13391339                                                newExpr->result = common ? common : r1->expr->result;
    13401340                                                // add candidate
    13411341                                                CandidateRef newCand = std::make_shared<Candidate>(
    1342                                                         newExpr, move( env ), move( open ), move( need ), 
     1342                                                        newExpr, move( env ), move( open ), move( need ),
    13431343                                                        r1->cost + r2->cost );
    13441344                                                inferParameters( newCand, candidates );
     
    13491349
    13501350                void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
    1351                         std::vector< CandidateFinder > subCandidates = 
     1351                        std::vector< CandidateFinder > subCandidates =
    13521352                                selfFinder.findSubExprs( tupleExpr->exprs );
    13531353                        std::vector< CandidateList > possibilities;
     
    13691369
    13701370                                addCandidate(
    1371                                         new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 
     1371                                        new ast::TupleExpr{ tupleExpr->location, move( exprs ) },
    13721372                                        move( env ), move( open ), move( need ), sumCost( subs ) );
    13731373                        }
     
    14111411                                toType = SymTab::validateType( initExpr->location, toType, symtab );
    14121412                                toType = adjustExprType( toType, tenv, symtab );
    1413                                 // The call to find must occur inside this loop, otherwise polymorphic return 
    1414                                 // types are not bound to the initialization type, since return type variables are 
    1415                                 // only open for the duration of resolving the UntypedExpr. 
     1413                                // The call to find must occur inside this loop, otherwise polymorphic return
     1414                                // types are not bound to the initialization type, since return type variables are
     1415                                // only open for the duration of resolving the UntypedExpr.
    14161416                                CandidateFinder finder{ symtab, tenv, toType };
    14171417                                finder.find( initExpr->expr, ResolvMode::withAdjustment() );
     
    14251425                                        )
    14261426
    1427                                         // It is possible that a cast can throw away some values in a multiply-valued 
    1428                                         // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 
    1429                                         // the subexpression results that are cast directly. The candidate is invalid 
     1427                                        // It is possible that a cast can throw away some values in a multiply-valued
     1428                                        // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of
     1429                                        // the subexpression results that are cast directly. The candidate is invalid
    14301430                                        // if it has fewer results than there are types to cast to.
    14311431                                        int discardedValues = cand->expr->result->size() - toType->size();
     
    14351435                                        unify( toType, cand->expr->result, env, need, have, open, symtab );
    14361436                                        Cost thisCost = castCost( cand->expr->result, toType, symtab, env );
    1437                                        
     1437
    14381438                                        if ( thisCost != Cost::infinity ) {
    14391439                                                // count one safe conversion for each value that is thrown away
    14401440                                                thisCost.incSafe( discardedValues );
    1441                                                 CandidateRef newCand = std::make_shared<Candidate>( 
    1442                                                         new ast::InitExpr{ 
    1443                                                                 initExpr->location, restructureCast( cand->expr, toType ), 
    1444                                                                 initAlt.designation }, 
     1441                                                CandidateRef newCand = std::make_shared<Candidate>(
     1442                                                        new ast::InitExpr{
     1443                                                                initExpr->location, restructureCast( cand->expr, toType ),
     1444                                                                initAlt.designation },
    14451445                                                        copy( cand->env ), move( open ), move( need ), cand->cost, thisCost );
    14461446                                                inferParameters( newCand, matches );
     
    14681468        };
    14691469
    1470         /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 
     1470        /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
    14711471        /// return type. Skips ambiguous candidates.
    14721472        CandidateList pruneCandidates( CandidateList & candidates ) {
     
    14931493                                if ( candidate->cost < found->second.candidate->cost ) {
    14941494                                        PRINT(
    1495                                                 std::cerr << "cost " << candidate->cost << " beats " 
     1495                                                std::cerr << "cost " << candidate->cost << " beats "
    14961496                                                        << found->second.candidate->cost << std::endl;
    14971497                                        )
     
    14991499                                        found->second = PruneStruct{ candidate };
    15001500                                } else if ( candidate->cost == found->second.candidate->cost ) {
    1501                                         // if one of the candidates contains a deleted identifier, can pick the other, 
    1502                                         // since deleted expressions should not be ambiguous if there is another option 
     1501                                        // if one of the candidates contains a deleted identifier, can pick the other,
     1502                                        // since deleted expressions should not be ambiguous if there is another option
    15031503                                        // that is at least as good
    15041504                                        if ( findDeletedExpr( candidate->expr ) ) {
     
    15141514                                } else {
    15151515                                        PRINT(
    1516                                                 std::cerr << "cost " << candidate->cost << " loses to " 
     1516                                                std::cerr << "cost " << candidate->cost << " loses to "
    15171517                                                        << found->second.candidate->cost << std::endl;
    15181518                                        )
     
    15291529
    15301530                        CandidateRef cand = target.second.candidate;
    1531                        
     1531
    15321532                        ast::ptr< ast::Type > newResult = cand->expr->result;
    15331533                        cand->env.applyFree( newResult );
    15341534                        cand->expr = ast::mutate_field(
    15351535                                cand->expr.get(), &ast::Expr::result, move( newResult ) );
    1536                        
     1536
    15371537                        out.emplace_back( cand );
    15381538                }
     
    15821582
    15831583                CandidateList pruned = pruneCandidates( candidates );
    1584                
     1584
    15851585                if ( mode.failFast && pruned.empty() ) {
    15861586                        std::ostringstream stream;
     
    16011601                )
    16021602                PRINT(
    1603                         std::cerr << "there are " << candidates.size() << " alternatives after elimination" 
     1603                        std::cerr << "there are " << candidates.size() << " alternatives after elimination"
    16041604                                << std::endl;
    16051605                )
    16061606        }
    16071607
    1608         // adjust types after pruning so that types substituted by pruneAlternatives are correctly 
     1608        // adjust types after pruning so that types substituted by pruneAlternatives are correctly
    16091609        // adjusted
    16101610        if ( mode.adjust ) {
    16111611                for ( CandidateRef & r : candidates ) {
    1612                         r->expr = ast::mutate_field( 
    1613                                 r->expr.get(), &ast::Expr::result, 
     1612                        r->expr = ast::mutate_field(
     1613                                r->expr.get(), &ast::Expr::result,
    16141614                                adjustExprType( r->expr->result, r->env, localSyms ) );
    16151615                }
     
    16241624}
    16251625
    1626 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 
    1627         const std::vector< ast::ptr< ast::Expr > > & xs 
     1626std::vector< CandidateFinder > CandidateFinder::findSubExprs(
     1627        const std::vector< ast::ptr< ast::Expr > > & xs
    16281628) {
    16291629        std::vector< CandidateFinder > out;
     
    16321632                out.emplace_back( localSyms, env );
    16331633                out.back().find( x, ResolvMode::withAdjustment() );
    1634                
     1634
    16351635                PRINT(
    16361636                        std::cerr << "findSubExprs" << std::endl;
  • src/ResolvExpr/CurrentObject.cc

    r504eb72 r2890212  
    2525#include "AST/Init.hpp"                // for Designation
    2626#include "AST/Node.hpp"                // for readonly
     27#include "AST/Print.hpp"                // for readonly
    2728#include "AST/Type.hpp"
    2829#include "Common/Indenter.h"           // for Indenter, operator<<
     
    596597                SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
    597598
    598                 void setPosition( 
    599                         std::deque< ptr< Expr > >::const_iterator begin, 
     599                void setPosition(
     600                        std::deque< ptr< Expr > >::const_iterator begin,
    600601                        std::deque< ptr< Expr > >::const_iterator end
    601602                ) override {
     
    637638                        auto res = eval(expr);
    638639                        if ( ! res.second ) {
    639                                 SemanticError( location, 
     640                                SemanticError( location,
    640641                                        toString("Array designator must be a constant expression: ", expr ) );
    641642                        }
     
    644645
    645646        public:
    646                 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) 
     647                ArrayIterator( const CodeLocation & loc, const ArrayType * at )
    647648                : location( loc ), array( at ), base( at->base ) {
    648649                        PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
     
    655656
    656657                void setPosition( const Expr * expr ) {
    657                         // need to permit integer-constant-expressions, including: integer constants, 
    658                         // enumeration constants, character constants, sizeof expressions, alignof expressions, 
     658                        // need to permit integer-constant-expressions, including: integer constants,
     659                        // enumeration constants, character constants, sizeof expressions, alignof expressions,
    659660                        // cast expressions
    660661                        if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) {
     
    662663                                        index = constExpr->intValue();
    663664                                } catch ( SemanticErrorException & ) {
    664                                         SemanticError( expr, 
     665                                        SemanticError( expr,
    665666                                                "Constant expression of non-integral type in array designator: " );
    666667                                }
    667668                        } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) {
    668669                                setPosition( castExpr->arg );
    669                         } else if ( 
    670                                 dynamic_cast< const SizeofExpr * >( expr ) 
    671                                 || dynamic_cast< const AlignofExpr * >( expr ) 
     670                        } else if (
     671                                dynamic_cast< const SizeofExpr * >( expr )
     672                                || dynamic_cast< const AlignofExpr * >( expr )
    672673                        ) {
    673674                                index = 0;
    674675                        } else {
    675                                 assertf( false, 
     676                                assertf( false,
    676677                                        "bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
    677678                        }
    678679                }
    679680
    680                 void setPosition( 
    681                         std::deque< ptr< Expr > >::const_iterator begin, 
     681                void setPosition(
     682                        std::deque< ptr< Expr > >::const_iterator begin,
    682683                        std::deque< ptr< Expr > >::const_iterator end
    683684                ) override {
     
    758759                }
    759760
    760                 AggregateIterator( 
    761                         const CodeLocation & loc, const std::string k, const std::string & n, const Type * i, 
     761                AggregateIterator(
     762                        const CodeLocation & loc, const std::string k, const std::string & n, const Type * i,
    762763                        const MemberList & ms )
    763                 : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ), 
     764                : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ),
    764765                  sub( genericSubstitution( i ) ) {
    765766                        PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
     
    768769
    769770        public:
    770                 void setPosition( 
    771                         std::deque< ptr< Expr > >::const_iterator begin, 
     771                void setPosition(
     772                        std::deque< ptr< Expr > >::const_iterator begin,
    772773                        std::deque< ptr< Expr > >::const_iterator end
    773774                ) final {
     
    786787                                        return;
    787788                                }
    788                                 assertf( false, 
     789                                assertf( false,
    789790                                        "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
    790791                        } else {
    791                                 assertf( false, 
     792                                assertf( false,
    792793                                        "bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() );
    793794                        }
     
    842843                                for ( InitAlternative & alt : ret ) {
    843844                                        PRINT( std::cerr << "iterating and adding designators" << std::endl; )
    844                                         alt.designation.get_and_mutate()->designators.emplace_front( 
     845                                        alt.designation.get_and_mutate()->designators.emplace_front(
    845846                                                new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
    846847                                }
     
    897898        class TupleIterator final : public AggregateIterator {
    898899        public:
    899                 TupleIterator( const CodeLocation & loc, const TupleType * inst ) 
    900                 : AggregateIterator( 
    901                         loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members 
     900                TupleIterator( const CodeLocation & loc, const TupleType * inst )
     901                : AggregateIterator(
     902                        loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members
    902903                ) {}
    903904
     
    926927                                return new UnionIterator{ loc, uit };
    927928                        } else {
    928                                 assertf( 
    929                                         dynamic_cast< const EnumInstType * >( aggr )
    930                                                 || dynamic_cast< const TypeInstType * >( aggr ),
     929                                assertf(
     930                                        dynamic_cast< const EnumInstType * >( type )
     931                                                || dynamic_cast< const TypeInstType * >( type ),
    931932                                        "Encountered unhandled ReferenceToType in createMemberIterator: %s",
    932933                                                toString( type ).c_str() );
     
    949950                using DesignatorChain = std::deque< ptr< Expr > >;
    950951                PRINT( std::cerr << "___findNext" << std::endl; )
    951                
     952
    952953                // find all the d's
    953954                std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts;
     
    10131014                // set new designators
    10141015                assertf( ! objStack.empty(), "empty object stack when setting designation" );
    1015                 Designation * actualDesignation = 
     1016                Designation * actualDesignation =
    10161017                        new Designation{ designation->location, DesignatorChain{d} };
    10171018                objStack.back()->setPosition( d ); // destroys d
  • src/ResolvExpr/Resolver.cc

    r504eb72 r2890212  
    10541054                        const ast::Expr * postmutate( const ast::CastExpr * castExpr ) {
    10551055                                if (
    1056                                         castExpr->isGenerated
     1056                                        castExpr->isGenerated == ast::GeneratedCast
    10571057                                        && typesCompatible( castExpr->arg->result, castExpr->result )
    10581058                                ) {
     
    13211321                // in case we decide to allow nested enums
    13221322                GuardValue( inEnumDecl );
    1323                 inEnumDecl = false;
     1323                inEnumDecl = true;
    13241324        }
    13251325
  • src/ResolvExpr/Unify.cc

    r504eb72 r2890212  
    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                #warning memory leak
    177170
    178171                return unifyExact(
    179                         newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     172                        env.apply( newFirst  ).node,
     173                        env.apply( newSecond ).node,
     174                        newEnv, need, have, open, noWiden(), symtab );
    180175        }
    181176
     
    326321
    327322        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;
    333323                AssertionSet::iterator i = assertions.find( assert );
    334324                if ( i != assertions.end() ) {
    335 ///     std::cerr << "found it!" << std::endl;
    336325                        i->second.isUsed = true;
    337326                } // if
     
    12021191                // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and
    12031192                // 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 );
     1193                ast::Type * t1 = shallowCopy(type1.get());
     1194                ast::Type * t2 = shallowCopy(type2.get());
     1195                t1->qualifiers = {};
     1196                t2->qualifiers = {};
     1197                #warning memory leak
    12071198
    12081199                if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
    1209                         t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
    1210 
    12111200                        // if exact unification on unqualified types, try to merge qualifiers
    12121201                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
    1213                                 common = type1;
    1214                                 reset_qualifiers( common, q1 | q2 );
     1202                                t1->qualifiers = q1 | q2;
     1203                                common = t1;
    12151204                                return true;
    12161205                        } else {
     
    12191208
    12201209                } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {
    1221                         t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
    1222 
    12231210                        // no exact unification, but common type
    1224                         reset_qualifiers( common, q1 | q2 );
     1211                        auto c = shallowCopy(common.get());
     1212                        c->qualifiers = q1 | q2;
     1213                        common = c;
    12251214                        return true;
    12261215                } else {
Note: See TracChangeset for help on using the changeset viewer.