Changes in / [849720f:4a60488]


Ignore:
Files:
6 added
1 deleted
40 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Attribute.hpp

    r849720f r4a60488  
    5151        template<typename node_t>
    5252        friend node_t * mutate(const node_t * node);
     53        template<typename node_t>
     54    friend node_t * shallowCopy(const node_t * node);
    5355};
    5456
  • src/AST/Convert.cpp

    r849720f r4a60488  
    608608
    609609                tgt->result = get<Type>().accept1(src->result);
     610                // Unconditionally use a clone of the result type.
     611                // We know this will leak some objects: much of the immediate conversion result.
     612                // In some cases, using the conversion result directly gives unintended object sharing.
     613                // A parameter (ObjectDecl, a child of a FunctionType) is shared by the weak-ref cache.
     614                // But tgt->result must be fully owned privately by tgt.
     615                // Applying these conservative copies here means
     616                // - weak references point at the declaration's copy, not these expr.result copies (good)
     617                // - we copy more objects than really needed (bad, tolerated)
     618                if (tgt->result) {
     619                        tgt->result = tgt->result->clone();
     620                }
    610621                return visitBaseExpr_skipResultType(src, tgt);
    611622        }
     
    21132124                                old->location,
    21142125                                GET_ACCEPT_1(member, DeclWithType),
    2115                                 GET_ACCEPT_1(aggregate, Expr)
     2126                                GET_ACCEPT_1(aggregate, Expr),
     2127                                ast::MemberExpr::NoOpConstructionChosen
    21162128                        )
    21172129                );
  • src/AST/Decl.cpp

    r849720f r4a60488  
    5252
    5353const Type * FunctionDecl::get_type() const { return type.get(); }
    54 void FunctionDecl::set_type(Type * t) { type = strict_dynamic_cast< FunctionType* >( t ); }
     54void FunctionDecl::set_type( const Type * t ) {
     55        type = strict_dynamic_cast< const FunctionType * >( t );
     56}
    5557
    5658// --- TypeDecl
  • src/AST/Decl.hpp

    r849720f r4a60488  
    3232
    3333// Must be included in *all* AST classes; should be #undef'd at the end of the file
    34 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     34#define MUTATE_FRIEND \
     35    template<typename node_t> friend node_t * mutate(const node_t * node); \
     36        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3537
    3638namespace ast {
     
    8789        virtual const Type * get_type() const = 0;
    8890        /// Set type of this declaration. May be verified by subclass
    89         virtual void set_type(Type *) = 0;
     91        virtual void set_type( const Type * ) = 0;
    9092
    9193        const DeclWithType * accept( Visitor & v ) const override = 0;
     
    110112
    111113        const Type* get_type() const override { return type; }
    112         void set_type( Type * ty ) override { type = ty; }
     114        void set_type( const Type * ty ) override { type = ty; }
    113115
    114116        const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
     
    132134
    133135        const Type * get_type() const override;
    134         void set_type(Type * t) override;
     136        void set_type( const Type * t ) override;
    135137
    136138        bool has_body() const { return stmts; }
     
    149151        std::vector<ptr<DeclWithType>> assertions;
    150152
    151         NamedTypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
    152                 Type* b, Linkage::Spec spec = Linkage::Cforall )
     153        NamedTypeDecl(
     154                const CodeLocation & loc, const std::string & name, Storage::Classes storage,
     155                const Type * b, Linkage::Spec spec = Linkage::Cforall )
    153156        : Decl( loc, name, storage, spec ), base( b ), params(), assertions() {}
    154157
     
    185188        };
    186189
    187         TypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, Type* b,
    188                 TypeVar::Kind k, bool s, Type* i = nullptr )
     190        TypeDecl(
     191                const CodeLocation & loc, const std::string & name, Storage::Classes storage,
     192                const Type * b, TypeVar::Kind k, bool s, const Type * i = nullptr )
    189193        : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeVar::Ttype || s ),
    190194          init( i ) {}
  • src/AST/Expr.cpp

    r849720f r4a60488  
    2020#include <vector>
    2121
     22#include "Copy.hpp"                // for shallowCopy
     23#include "Eval.hpp"                // for call
    2224#include "GenericSubstitution.hpp"
    2325#include "Stmt.hpp"
     
    5153        assert( arg );
    5254
    53         UntypedExpr * ret = new UntypedExpr{
    54                 loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } }
    55         };
     55        UntypedExpr * ret = call( loc, "*?", arg );
    5656        if ( const Type * ty = arg->result ) {
    5757                const Type * base = InitTweak::getPointerBase( ty );
     
    7474        assert( lhs && rhs );
    7575
    76         UntypedExpr * ret = new UntypedExpr{
    77                 loc, new NameExpr{loc, "?=?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ lhs }, ptr<Expr>{ rhs } }
    78         };
     76        UntypedExpr * ret = call( loc, "?=?", lhs, rhs );
    7977        if ( lhs->result && rhs->result ) {
    8078                // if both expressions are typed, assumes that this assignment is a C bitwise assignment,
     
    160158        assert( aggregate->result );
    161159
    162         // take ownership of member type
    163         result = mem->get_type();
     160        // Deep copy on result type avoids mutation on transitively multiply referenced object.
     161        //
     162        // Example, adapted from parts of builtins and bootloader:
     163        //
     164        // forall(dtype T)
     165        // struct __Destructor {
     166        //   T * object;
     167        //   void (*dtor)(T *);
     168        // };
     169        //
     170        // forall(dtype S)
     171        // void foo(__Destructor(S) &d) {
     172        //   if (d.dtor) {  // here
     173        //   }
     174        // }
     175        //
     176        // Let e be the "d.dtor" guard espression, which is MemberExpr after resolve.  Let d be the
     177        // declaration of member __Destructor.dtor (an ObjectDecl), as accessed via the top-level
     178        // declaration of __Destructor.  Consider the types e.result and d.type.  In the old AST, one
     179        // is a clone of the other.  Ordinary new-AST use would set them up as a multiply-referenced
     180        // object.
     181        //
     182        // e.result: PointerType
     183        // .base: FunctionType
     184        // .params.front(): ObjectDecl, the anonymous parameter of type T*
     185        // .type: PointerType
     186        // .base: TypeInstType
     187        // let x = that
     188        // let y = similar, except start from d.type
     189        //
     190        // Consider two code lines down, genericSubstitution(...).apply(result).
     191        //
     192        // Applying this chosen-candidate's type substitution means modifying x, substituting
     193        // S for T.  This mutation should affect x and not y.
     194
     195        result = deepCopy(mem->get_type());
     196
    164197        // substitute aggregate generic parameters into member type
    165198        genericSubstitution( aggregate->result ).apply( result );
     
    168201}
    169202
     203MemberExpr::MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
     204    MemberExpr::NoOpConstruction overloadSelector )
     205: Expr( loc ), member( mem ), aggregate( agg ) {
     206        assert( member );
     207        assert( aggregate );
     208        assert( aggregate->result );
     209        (void) overloadSelector;
     210}
     211
    170212// --- VariableExpr
    171213
     
    177219        assert( var );
    178220        assert( var->get_type() );
    179         result = var->get_type();
    180         add_qualifiers( result, CV::Lvalue );
     221        auto r = shallowCopy( var->get_type() );
     222        r->qualifiers |= CV::Lvalue;
     223        result = r;
    181224}
    182225
  • src/AST/Expr.hpp

    r849720f r4a60488  
    3030
    3131// Must be included in *all* AST classes; should be #undef'd at the end of the file
    32 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     32#define MUTATE_FRIEND \
     33    template<typename node_t> friend node_t * mutate(const node_t * node); \
     34        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
     35
    3336
    3437class ConverterOldToNew;
     
    355358        MemberExpr * clone() const override { return new MemberExpr{ *this }; }
    356359        MUTATE_FRIEND
     360
     361        // Custructor overload meant only for AST conversion
     362        enum NoOpConstruction { NoOpConstructionChosen };
     363        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
     364            NoOpConstruction overloadSelector );
     365        friend class ::ConverterOldToNew;
     366        friend class ::ConverterNewToOld;
    357367};
    358368
     
    531541
    532542        CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
    533         : Expr( loc ), arg1( a1 ), arg2( a2 ) {}
     543        : Expr( loc ), arg1( a1 ), arg2( a2 ) {
     544                this->result = a2->result;
     545        }
    534546
    535547        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Init.hpp

    r849720f r4a60488  
    2525
    2626// Must be included in *all* AST classes; should be #undef'd at the end of the file
    27 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     27#define MUTATE_FRIEND \
     28    template<typename node_t> friend node_t * mutate(const node_t * node); \
     29        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    2830
    2931namespace ast {
  • src/AST/Node.cpp

    r849720f r4a60488  
    1717#include "Fwd.hpp"
    1818
     19#include <csignal>  // MEMORY DEBUG -- for raise
    1920#include <iostream>
    2021
     
    2930#include "Print.hpp"
    3031
    31 template< typename node_t, enum ast::Node::ref_type ref_t >
    32 void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) { node->increment(ref_t); }
    33 
    34 template< typename node_t, enum ast::Node::ref_type ref_t >
    35 void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node ) { node->decrement(ref_t); }
    36 
    37 template< typename node_t, enum ast::Node::ref_type ref_t >
    38 void ast::ptr_base<node_t, ref_t>::_check() const { if(node) assert(node->was_ever_strong == false || node->strong_count > 0); }
     32/// MEMORY DEBUG -- allows breaking on ref-count changes of dynamically chosen object.
     33/// Process to use in GDB:
     34///   break ast::Node::_trap()
     35///   run
     36///   set variable MEM_TRAP_OBJ = <target>
     37///   disable <first breakpoint>
     38///   continue
     39void * MEM_TRAP_OBJ = nullptr;
     40
     41void _trap( const void * node ) {
     42        if ( node == MEM_TRAP_OBJ ) std::raise(SIGTRAP);
     43}
     44
     45template< typename node_t, enum ast::Node::ref_type ref_t >
     46void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) {
     47        node->increment(ref_t);
     48        _trap( node );
     49}
     50
     51template< typename node_t, enum ast::Node::ref_type ref_t >
     52void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node, bool do_delete ) {
     53        _trap( node );
     54        node->decrement(ref_t, do_delete );
     55}
     56
     57template< typename node_t, enum ast::Node::ref_type ref_t >
     58void ast::ptr_base<node_t, ref_t>::_check() const {
     59        // if(node) assert(node->was_ever_strong == false || node->strong_count > 0);
     60}
    3961
    4062template< typename node_t, enum ast::Node::ref_type ref_t >
  • src/AST/Node.hpp

    r849720f r4a60488  
    3838        Node& operator= (const Node&) = delete;
    3939        Node& operator= (Node&&) = delete;
    40         virtual ~Node() = default;
     40        virtual ~Node() {}
    4141
    4242        virtual const Node * accept( Visitor & v ) const = 0;
     
    5757        template<typename node_t>
    5858        friend node_t * mutate(const node_t * node);
     59        template<typename node_t>
     60        friend node_t * shallowCopy(const node_t * node);
    5961
    6062        mutable size_t strong_count = 0;
     
    6971        }
    7072
    71         void decrement(ast::Node::ref_type ref) const {
     73        void decrement(ast::Node::ref_type ref, bool do_delete = true) const {
    7274                switch (ref) {
    7375                        case ref_type::strong: strong_count--; break;
     
    7577                }
    7678
    77                 if(!strong_count && !weak_count) {
     79                if( do_delete && !strong_count && !weak_count) {
    7880                        delete this;
    7981                }
     
    9496        assertf(
    9597                node->weak_count == 0,
    96                 "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"
    9799        );
    98100        return node->clone();
     
    104106        // skip mutate if equivalent
    105107        if ( node->*field == val ) return node;
    106        
     108
    107109        // mutate and return
    108110        node_t * ret = mutate( node );
     
    123125        (ret->*field)[i] = std::forward< field_t >( val );
    124126        return ret;
     127}
     128
     129/// Mutate an entire indexed collection by cloning to accepted value
     130template<typename node_t, typename parent_t, typename coll_t>
     131const node_t * mutate_each( const node_t * node, coll_t parent_t::* field, Visitor & v ) {
     132        for ( unsigned i = 0; i < (node->*field).size(); ++i ) {
     133                node = mutate_field_index( node, field, i, (node->*field)[i]->accept( v ) );
     134        }
     135        return node;
    125136}
    126137
     
    219230        operator const node_t * () const { _check(); return node; }
    220231
     232        const node_t * release() {
     233                const node_t * ret = node;
     234                if ( node ) {
     235                        _dec(node, false);
     236                        node = nullptr;
     237                }
     238                return ret;
     239        }
     240
    221241        /// wrapper for convenient access to dynamic_cast
    222242        template<typename o_node_t>
     
    244264
    245265        void _inc( const node_t * other );
    246         void _dec( const node_t * other );
     266        void _dec( const node_t * other, bool do_delete = true );
    247267        void _check() const;
    248268
  • src/AST/Pass.hpp

    r849720f r4a60488  
    3535#include "AST/SymbolTable.hpp"
    3636
     37#include "AST/ForallSubstitutionTable.hpp"
     38
    3739// Private prelude header, needed for some of the magic tricks this class pulls off
    3840#include "AST/Pass.proto.hpp"
     
    4648//
    4749// Several additional features are available through inheritance
    48 // | WithTypeSubstitution - provides polymorphic const TypeSubstitution * env for the
    49 //                          current expression
    50 // | WithStmtsToAdd       - provides the ability to insert statements before or after the current
    51 //                          statement by adding new statements into stmtsToAddBefore or
    52 //                          stmtsToAddAfter respectively.
    53 // | WithDeclsToAdd       - provides the ability to insert declarations before or after the current
    54 //                          declarations by adding new DeclStmt into declsToAddBefore or
    55 //                          declsToAddAfter respectively.
    56 // | WithShortCircuiting  - provides the ability to skip visiting child nodes; set visit_children
    57 //                          to false in pre{visit,visit} to skip visiting children
    58 // | WithGuards           - provides the ability to save/restore data like a LIFO stack; to save,
    59 //                          call GuardValue with the variable to save, the variable will
    60 //                          automatically be restored to its previous value after the corresponding
    61 //                          postvisit/postmutate teminates.
    62 // | WithVisitorRef       - provides an pointer to the templated visitor wrapper
    63 // | WithSymbolTable      - provides symbol table functionality
     50// | WithTypeSubstitution  - provides polymorphic const TypeSubstitution * env for the
     51//                           current expression
     52// | WithStmtsToAdd        - provides the ability to insert statements before or after the current
     53//                           statement by adding new statements into stmtsToAddBefore or
     54//                           stmtsToAddAfter respectively.
     55// | WithDeclsToAdd        - provides the ability to insert declarations before or after the
     56//                           current declarations by adding new DeclStmt into declsToAddBefore or
     57//                           declsToAddAfter respectively.
     58// | WithShortCircuiting   - provides the ability to skip visiting child nodes; set visit_children
     59//                           to false in pre{visit,visit} to skip visiting children
     60// | WithGuards            - provides the ability to save/restore data like a LIFO stack; to save,
     61//                           call GuardValue with the variable to save, the variable will
     62//                           automatically be restored to its previous value after the
     63//                           corresponding postvisit/postmutate teminates.
     64// | WithVisitorRef        - provides an pointer to the templated visitor wrapper
     65// | WithSymbolTable       - provides symbol table functionality
     66// | WithForallSubstitutor - maintains links between TypeInstType and TypeDecl under mutation
    6467//-------------------------------------------------------------------------------------------------
    6568template< typename pass_t >
     
    201204        container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
    202205
     206        /// Mutate forall-list, accounting for presence of type substitution map
     207        template<typename node_t>
     208        void mutate_forall( const node_t *& );
     209
    203210public:
    204211        /// Logic to call the accept and mutate the parent if needed, delegates call to accept
     
    209216        /// Internal RAII guard for symbol table features
    210217        struct guard_symtab {
    211                 guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass, 0); }
    212                 ~guard_symtab()                                   { __pass::symtab::leave(pass, 0); }
     218                guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass.pass, 0); }
     219                ~guard_symtab()                                   { __pass::symtab::leave(pass.pass, 0); }
    213220                Pass<pass_t> & pass;
    214221        };
     
    216223        /// Internal RAII guard for scope features
    217224        struct guard_scope {
    218                 guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass, 0); }
    219                 ~guard_scope()                                   { __pass::scope::leave(pass, 0); }
     225                guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass.pass, 0); }
     226                ~guard_scope()                                   { __pass::scope::leave(pass.pass, 0); }
    220227                Pass<pass_t> & pass;
     228        };
     229
     230        /// Internal RAII guard for forall substitutions
     231        struct guard_forall_subs {
     232                guard_forall_subs( Pass<pass_t> & pass, const ParameterizedType * type )
     233                : pass( pass ), type( type ) { __pass::forall::enter(pass.pass, 0, type ); }
     234                ~guard_forall_subs()         { __pass::forall::leave(pass.pass, 0, type ); }
     235                Pass<pass_t> & pass;
     236                const ParameterizedType * type;
    221237        };
    222238
     
    313329        SymbolTable symtab;
    314330};
     331
     332/// Use when the templated visitor needs to keep TypeInstType instances properly linked to TypeDecl
     333struct WithForallSubstitutor {
     334        ForallSubstitutionTable subs;
     335};
     336
    315337}
    316338
  • src/AST/Pass.impl.hpp

    r849720f r4a60488  
    127127                        , decltype( node->accept(*this) )
    128128                >::type
    129 
    130129        {
    131130                __pedantic_pass_assert( __visit_children() );
    132                 __pedantic_pass_assert( expr );
     131                __pedantic_pass_assert( node );
    133132
    134133                static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR");
     
    323322        }
    324323
     324
     325        template< typename pass_t >
     326        template< typename node_t >
     327        void ast::Pass< pass_t >::mutate_forall( const node_t *& node ) {
     328                if ( auto subs = __pass::forall::subs( pass, 0 ) ) {
     329                        // tracking TypeDecl substitution, full clone
     330                        if ( node->forall.empty() ) return;
     331
     332                        node_t * mut = mutate( node );
     333                        mut->forall = subs->clone( node->forall, *this );
     334                        node = mut;
     335                } else {
     336                        // not tracking TypeDecl substitution, just mutate
     337                        maybe_accept( node, &node_t::forall );
     338                }
     339        }
    325340}
    326341
     
    429444                        guard_symtab guard { *this };
    430445                        // implicit add __func__ identifier as specified in the C manual 6.4.2.2
    431                         static ast::ObjectDecl func(
    432                                 node->location, "__func__",
    433                                 new ast::ArrayType(
    434                                         new ast::BasicType( ast::BasicType::Char, ast::CV::Qualifiers( ast::CV::Const ) ),
     446                        static ast::ptr< ast::ObjectDecl > func{ new ast::ObjectDecl{
     447                                CodeLocation{}, "__func__",
     448                                new ast::ArrayType{
     449                                        new ast::BasicType{ ast::BasicType::Char, ast::CV::Const },
    435450                                        nullptr, VariableLen, DynamicDim
    436                                 )
    437                         );
    438                         __pass::symtab::addId( pass, 0, &func );
     451                                }
     452                        } };
     453                        __pass::symtab::addId( pass, 0, func );
    439454                        VISIT(
    440455                                maybe_accept( node, &FunctionDecl::type );
     
    610625        VISIT({
    611626                // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    612                 auto guard1 = makeFuncGuard( [this, inFunction = this->inFunction]() {
    613                         if ( ! inFunction ) __pass::symtab::enter(pass, 0);
    614                 }, [this, inFunction = this->inFunction]() {
    615                         if ( ! inFunction ) __pass::symtab::leave(pass, 0);
     627                auto guard1 = makeFuncGuard( [this, inFunctionCpy = this->inFunction]() {
     628                        if ( ! inFunctionCpy ) __pass::symtab::enter(pass, 0);
     629                }, [this, inFunctionCpy = this->inFunction]() {
     630                        if ( ! inFunctionCpy ) __pass::symtab::leave(pass, 0);
    616631                });
    617632                ValueGuard< bool > guard2( inFunction );
     
    938953        // For now this isn't visited, it is unclear if this causes problem
    939954        // if all tests are known to pass, remove this code
    940         // VISIT(
    941         //      maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
    942         // )
     955        VISIT(
     956                maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
     957        )
    943958
    944959        VISIT_END( Stmt, node );
     
    16671682        VISIT_START( node );
    16681683
    1669         VISIT(
    1670                 maybe_accept( node, &FunctionType::forall  );
     1684        VISIT({
     1685                guard_forall_subs forall_guard { *this, node };
     1686                mutate_forall( node );
    16711687                maybe_accept( node, &FunctionType::returns );
    16721688                maybe_accept( node, &FunctionType::params  );
    1673         )
     1689        })
    16741690
    16751691        VISIT_END( Type, node );
     
    16861702        VISIT({
    16871703                guard_symtab guard { *this };
    1688                 maybe_accept( node, &StructInstType::forall );
     1704                guard_forall_subs forall_guard { *this, node };
     1705                mutate_forall( node );
    16891706                maybe_accept( node, &StructInstType::params );
    16901707        })
     
    16991716        VISIT_START( node );
    17001717
    1701         __pass::symtab::addStruct( pass, 0, node->name );
    1702 
    1703         {
     1718        __pass::symtab::addUnion( pass, 0, node->name );
     1719
     1720        VISIT({
    17041721                guard_symtab guard { *this };
    1705                 maybe_accept( node, &UnionInstType::forall );
     1722                guard_forall_subs forall_guard { *this, node };
     1723                mutate_forall( node );
    17061724                maybe_accept( node, &UnionInstType::params );
    1707         }
     1725        })
    17081726
    17091727        VISIT_END( Type, node );
     
    17161734        VISIT_START( node );
    17171735
    1718         VISIT(
    1719                 maybe_accept( node, &EnumInstType::forall );
     1736        VISIT({
     1737                guard_forall_subs forall_guard { *this, node };
     1738                mutate_forall( node );
    17201739                maybe_accept( node, &EnumInstType::params );
    1721         )
     1740        })
    17221741
    17231742        VISIT_END( Type, node );
     
    17301749        VISIT_START( node );
    17311750
    1732         VISIT(
    1733                 maybe_accept( node, &TraitInstType::forall );
     1751        VISIT({
     1752                guard_forall_subs forall_guard { *this, node };
     1753                mutate_forall( node );
    17341754                maybe_accept( node, &TraitInstType::params );
    1735         )
     1755        })
    17361756
    17371757        VISIT_END( Type, node );
     
    17451765
    17461766        VISIT(
    1747                 maybe_accept( node, &TypeInstType::forall );
    1748                 maybe_accept( node, &TypeInstType::params );
     1767                {
     1768                        guard_forall_subs forall_guard { *this, node };
     1769                        mutate_forall( node );
     1770                        maybe_accept( node, &TypeInstType::params );
     1771                }
     1772                // ensure that base re-bound if doing substitution
     1773                __pass::forall::replace( pass, 0, node );
    17491774        )
    17501775
     
    18951920                                guard_symtab guard { *this };
    18961921                                auto new_node = p.second->accept( *this );
    1897                                 if (new_node != p.second) mutated = false;
     1922                                if (new_node != p.second) mutated = true;
    18981923                                new_map.insert({ p.first, new_node });
    18991924                        }
     
    19111936                                guard_symtab guard { *this };
    19121937                                auto new_node = p.second->accept( *this );
    1913                                 if (new_node != p.second) mutated = false;
     1938                                if (new_node != p.second) mutated = true;
    19141939                                new_map.insert({ p.first, new_node });
    19151940                        }
  • src/AST/Pass.proto.hpp

    r849720f r4a60488  
    263263                template<typename pass_t>
    264264                static inline void leave( pass_t &, long ) {}
    265         };
    266 
    267         // Finally certain pass desire an up to date symbol table automatically
     265        } // namespace scope
     266
     267        // Certain passes desire an up to date symbol table automatically
    268268        // detect the presence of a member name `symtab` and call all the members appropriately
    269269        namespace symtab {
    270270                // Some simple scoping rules
    271271                template<typename pass_t>
    272                 static inline auto enter( pass_t & pass, int ) -> decltype( pass.symtab.enterScope(), void() ) {
     272                static inline auto enter( pass_t & pass, int ) -> decltype( pass.symtab, void() ) {
    273273                        pass.symtab.enterScope();
    274274                }
     
    278278
    279279                template<typename pass_t>
    280                 static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab.leaveScope(), void() ) {
     280                static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab, void() ) {
    281281                        pass.symtab.leaveScope();
    282282                }
     
    356356                #undef SYMTAB_FUNC1
    357357                #undef SYMTAB_FUNC2
    358         };
    359 };
    360 };
     358        } // namespace symtab
     359
     360        // Some passes need to mutate TypeDecl and properly update their pointing TypeInstType.
     361        // Detect the presence of a member name `subs` and call all members appropriately
     362        namespace forall {
     363                // Some simple scoping rules
     364                template<typename pass_t>
     365                static inline auto enter( pass_t & pass, int, const ast::ParameterizedType * type )
     366                -> decltype( pass.subs, void() ) {
     367                        if ( ! type->forall.empty() ) pass.subs.beginScope();
     368                }
     369
     370                template<typename pass_t>
     371                static inline auto enter( pass_t &, long, const ast::ParameterizedType * ) {}
     372
     373                template<typename pass_t>
     374                static inline auto leave( pass_t & pass, int, const ast::ParameterizedType * type )
     375                -> decltype( pass.subs, void() ) {
     376                        if ( ! type->forall.empty() ) { pass.subs.endScope(); }
     377                }
     378
     379                template<typename pass_t>
     380                static inline auto leave( pass_t &, long, const ast::ParameterizedType * ) {}
     381
     382                // Get the substitution table, if present
     383                template<typename pass_t>
     384                static inline auto subs( pass_t & pass, int ) -> decltype( &pass.subs ) {
     385                        return &pass.subs;
     386                }
     387               
     388                template<typename pass_t>
     389                static inline ast::ForallSubstitutionTable * subs( pass_t &, long ) { return nullptr; }
     390
     391                // Replaces a TypeInstType's base TypeDecl according to the table
     392                template<typename pass_t>
     393                static inline auto replace( pass_t & pass, int, const ast::TypeInstType *& inst )
     394                -> decltype( pass.subs, void() ) {
     395                        inst = ast::mutate_field(
     396                                inst, &ast::TypeInstType::base, pass.subs.replace( inst->base ) );
     397                }
     398
     399                template<typename pass_t>
     400                static inline auto replace( pass_t &, long, const ast::TypeInstType *& ) {}
     401
     402        } // namespace forall
     403} // namespace __pass
     404} // namespace ast
  • src/AST/Stmt.hpp

    r849720f r4a60488  
    2727
    2828// Must be included in *all* AST classes; should be #undef'd at the end of the file
    29 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     29#define MUTATE_FRIEND \
     30    template<typename node_t> friend node_t * mutate(const node_t * node); \
     31        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3032
    3133namespace ast {
     
    397399class ImplicitCtorDtorStmt final : public Stmt {
    398400public:
    399         readonly<Stmt> callStmt;
     401        ptr<Stmt> callStmt;
    400402
    401403        ImplicitCtorDtorStmt( const CodeLocation & loc, const Stmt * callStmt,
  • src/AST/Type.cpp

    r849720f r4a60488  
    2121
    2222#include "Decl.hpp"
     23#include "ForallSubstitutor.hpp" // for substituteForall
    2324#include "Init.hpp"
     25#include "Common/utility.h"      // for copy, move
    2426#include "InitTweak/InitTweak.h" // for getPointerBase
    2527#include "Tuples/Tuples.h"       // for isTtype
     
    9193);
    9294
     95// --- ParameterizedType
     96
     97void ParameterizedType::initWithSub(
     98        const ParameterizedType & o, Pass< ForallSubstitutor > & sub
     99) {
     100        forall = sub.pass( o.forall );
     101}
     102
    93103// --- FunctionType
     104
     105FunctionType::FunctionType( const FunctionType & o )
     106: ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(),
     107  isVarArgs( o.isVarArgs ) {
     108        Pass< ForallSubstitutor > sub;
     109        initWithSub( o, sub );           // initialize substitution map
     110        returns = sub.pass( o.returns ); // apply to return and parameter types
     111        params = sub.pass( o.params );
     112}
    94113
    95114namespace {
     
    107126
    108127// --- ReferenceToType
     128
     129void ReferenceToType::initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub ) {
     130        ParameterizedType::initWithSub( o, sub ); // initialize substitution
     131        params = sub.pass( o.params );            // apply to parameters
     132}
     133
     134ReferenceToType::ReferenceToType( const ReferenceToType & o )
     135: ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ),
     136  hoistType( o.hoistType ) {
     137        Pass< ForallSubstitutor > sub;
     138        initWithSub( o, sub );
     139}
     140
    109141std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const {
    110142        assertf( aggr(), "Must have aggregate to perform lookup" );
     
    119151// --- StructInstType
    120152
    121 StructInstType::StructInstType( const StructDecl * b, CV::Qualifiers q,
    122         std::vector<ptr<Attribute>>&& as )
    123 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     153StructInstType::StructInstType(
     154        const StructDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
     155: ReferenceToType( b->name, q, move(as) ), base( b ) {}
    124156
    125157bool StructInstType::isComplete() const { return base ? base->body : false; }
     
    127159// --- UnionInstType
    128160
    129 UnionInstType::UnionInstType( const UnionDecl * b, CV::Qualifiers q,
    130         std::vector<ptr<Attribute>>&& as )
    131 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     161UnionInstType::UnionInstType(
     162        const UnionDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
     163: ReferenceToType( b->name, q, move(as) ), base( b ) {}
    132164
    133165bool UnionInstType::isComplete() const { return base ? base->body : false; }
     
    135167// --- EnumInstType
    136168
    137 EnumInstType::EnumInstType( const EnumDecl * b, CV::Qualifiers q,
    138         std::vector<ptr<Attribute>>&& as )
    139 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     169EnumInstType::EnumInstType(
     170        const EnumDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
     171: ReferenceToType( b->name, q, move(as) ), base( b ) {}
    140172
    141173bool EnumInstType::isComplete() const { return base ? base->body : false; }
     
    143175// --- TraitInstType
    144176
    145 TraitInstType::TraitInstType( const TraitDecl * b, CV::Qualifiers q,
    146         std::vector<ptr<Attribute>>&& as )
    147 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     177TraitInstType::TraitInstType(
     178        const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
     179: ReferenceToType( b->name, q, move(as) ), base( b ) {}
    148180
    149181// --- TypeInstType
     182
     183TypeInstType::TypeInstType( const TypeInstType & o )
     184: ReferenceToType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {
     185        Pass< ForallSubstitutor > sub;
     186        initWithSub( o, sub );      // initialize substitution
     187        base = sub.pass( o.base );  // apply to base type
     188}
    150189
    151190void TypeInstType::set_base( const TypeDecl * b ) {
     
    159198
    160199TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q )
    161 : Type( q ), types( std::move(ts) ), members() {
     200: Type( q ), types( move(ts) ), members() {
    162201        // This constructor is awkward. `TupleType` needs to contain objects so that members can be
    163202        // named, but members without initializer nodes end up getting constructors, which breaks
  • src/AST/Type.hpp

    r849720f r4a60488  
    3030
    3131// Must be included in *all* AST classes; should be #undef'd at the end of the file
    32 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     32#define MUTATE_FRIEND \
     33    template<typename node_t> friend node_t * mutate(const node_t * node); \
     34        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3335
    3436namespace ast {
     37
     38template< typename T > class Pass;
     39
     40struct ForallSubstitutor;
    3541
    3642class Type : public Node {
     
    164170        static const char *typeNames[];
    165171
    166         BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 
     172        BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    167173        : Type(q, std::move(as)), kind(k) {}
    168174
     
    266272/// Base type for potentially forall-qualified types
    267273class ParameterizedType : public Type {
     274protected:
     275        /// initializes forall with substitutor
     276        void initWithSub( const ParameterizedType & o, Pass< ForallSubstitutor > & sub );
    268277public:
    269278        using ForallList = std::vector<ptr<TypeDecl>>;
     
    277286        ParameterizedType( CV::Qualifiers q, std::vector<ptr<Attribute>> && as = {} )
    278287        : Type(q, std::move(as)), forall() {}
     288
     289        // enforce use of ForallSubstitutor to copy parameterized type
     290        ParameterizedType( const ParameterizedType & ) = delete;
     291
     292        ParameterizedType( ParameterizedType && ) = default;
     293
     294        // no need to change destructor, and operator= deleted in Node
    279295
    280296private:
     
    302318        : ParameterizedType(q), returns(), params(), isVarArgs(va) {}
    303319
     320        FunctionType( const FunctionType & o );
     321
    304322        /// true if either the parameters or return values contain a tttype
    305323        bool isTtype() const;
     
    315333/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
    316334class ReferenceToType : public ParameterizedType {
     335protected:
     336        /// Initializes forall and parameters based on substitutor
     337        void initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub );
    317338public:
    318339        std::vector<ptr<Expr>> params;
     
    320341        bool hoistType = false;
    321342
    322         ReferenceToType( const std::string& n, CV::Qualifiers q = {},
    323                 std::vector<ptr<Attribute>> && as = {} )
     343        ReferenceToType(
     344                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    324345        : ParameterizedType(q, std::move(as)), params(), name(n) {}
     346
     347        ReferenceToType( const ReferenceToType & o );
    325348
    326349        /// Gets aggregate declaration this type refers to
     
    339362        readonly<StructDecl> base;
    340363
    341         StructInstType( const std::string& n, CV::Qualifiers q = {},
    342                 std::vector<ptr<Attribute>> && as = {} )
     364        StructInstType(
     365                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    343366        : ReferenceToType( n, q, std::move(as) ), base() {}
    344         StructInstType( const StructDecl * b, CV::Qualifiers q = {},
    345                 std::vector<ptr<Attribute>> && as = {} );
     367
     368        StructInstType(
     369                const StructDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    346370
    347371        bool isComplete() const override;
     
    360384        readonly<UnionDecl> base;
    361385
    362         UnionInstType( const std::string& n, CV::Qualifiers q = {},
    363                 std::vector<ptr<Attribute>> && as = {} )
     386        UnionInstType(
     387                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    364388        : ReferenceToType( n, q, std::move(as) ), base() {}
    365         UnionInstType( const UnionDecl * b, CV::Qualifiers q = {},
    366                 std::vector<ptr<Attribute>> && as = {} );
     389
     390        UnionInstType(
     391                const UnionDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    367392
    368393        bool isComplete() const override;
     
    381406        readonly<EnumDecl> base;
    382407
    383         EnumInstType( const std::string& n, CV::Qualifiers q = {},
    384                 std::vector<ptr<Attribute>> && as = {} )
     408        EnumInstType(
     409                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    385410        : ReferenceToType( n, q, std::move(as) ), base() {}
    386         EnumInstType( const EnumDecl * b, CV::Qualifiers q = {},
    387                 std::vector<ptr<Attribute>> && as = {} );
     411
     412        EnumInstType(
     413                const EnumDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    388414
    389415        bool isComplete() const override;
     
    402428        readonly<TraitDecl> base;
    403429
    404         TraitInstType( const std::string& n, CV::Qualifiers q = {},
    405                 std::vector<ptr<Attribute>> && as = {} )
     430        TraitInstType(
     431                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    406432        : ReferenceToType( n, q, std::move(as) ), base() {}
    407         TraitInstType( const TraitDecl * b, CV::Qualifiers q = {},
    408                 std::vector<ptr<Attribute>> && as = {} );
     433
     434        TraitInstType(
     435                const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    409436
    410437        // not meaningful for TraitInstType
     
    425452        TypeVar::Kind kind;
    426453
    427         TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
     454        TypeInstType(
     455                const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
    428456                std::vector<ptr<Attribute>> && as = {} )
    429457        : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
    430         TypeInstType( const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {},
     458
     459        TypeInstType(
     460                const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {},
    431461                std::vector<ptr<Attribute>> && as = {} )
    432462        : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
     463
     464        TypeInstType( const TypeInstType & o );
    433465
    434466        /// sets `base`, updating `kind` correctly
  • src/AST/TypeEnvironment.hpp

    r849720f r4a60488  
    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

    r849720f r4a60488  
    9292namespace {
    9393        struct EnvTrimmer {
    94                 ptr<TypeSubstitution> env;
     94                const TypeSubstitution * env;
    9595                TypeSubstitution * newEnv;
    9696                EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
     
    108108        if ( env ) {
    109109                TypeSubstitution * newEnv = new TypeSubstitution();
    110 #if TIME_TO_CONVERT_PASSES
    111110                Pass<EnvTrimmer> trimmer( env, newEnv );
    112111                expr->accept( trimmer );
    113 #else
    114                 (void)expr;
    115                 (void)env;
    116 #endif
    117112                return newEnv;
    118113        }
     
    121116
    122117void TypeSubstitution::normalize() {
    123 #if TIME_TO_CONVERT_PASSES
    124         PassVisitor<Substituter> sub( *this, true );
     118        Pass<Substituter> sub( *this, true );
    125119        do {
    126120                sub.pass.subCount = 0;
    127121                sub.pass.freeOnly = true;
    128122                for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
    129                         i->second = i->second->acceptMutator( sub );
     123                        i->second = i->second->accept( sub );
    130124                }
    131125        } while ( sub.pass.subCount );
    132 #endif
    133 }
    134 
    135 #if TIME_TO_CONVERT_PASSES
    136 
    137 Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) {
     126}
     127
     128const Type * TypeSubstitution::Substituter::postvisit( const TypeInstType *inst ) {
    138129        BoundVarsType::const_iterator bound = boundVars.find( inst->name );
    139130        if ( bound != boundVars.end() ) return inst;
     
    146137                // Note: this does not prevent cycles in the general case, so it may be necessary to do something more sophisticated here.
    147138                // TODO: investigate preventing type variables from being bound to themselves in the first place.
    148                 if ( TypeInstType * replacement = i->second.as<TypeInstType>() ) {
     139                if ( const TypeInstType * replacement = i->second.as<TypeInstType>() ) {
    149140                        if ( inst->name == replacement->name ) {
    150141                                return inst;
     
    153144                // std::cerr << "found " << inst->name << ", replacing with " << i->second << std::endl;
    154145                subCount++;
    155                 Type * newtype = i->second->clone();
    156                 newtype->get_qualifiers() |= inst->get_qualifiers();
    157                 delete inst;
    158                 // Note: need to recursively apply substitution to the new type because normalize does not substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
    159                 return newtype->acceptMutator( *visitor );
    160         } // if
    161 }
    162 
    163 Expression * TypeSubstitution::Substituter::postmutate( NameExpr * nameExpr ) {
     146                ptr<Type> newType = i->second; // force clone if needed
     147                add_qualifiers( newType, inst->qualifiers );
     148                // Note: need to recursively apply substitution to the new type because normalize does not
     149                // substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
     150                newType = newType->accept( *visitor );
     151                return newType.release();
     152        } // if
     153}
     154
     155const Expr * TypeSubstitution::Substituter::postvisit( const NameExpr * nameExpr ) {
    164156        VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name );
    165157        if ( i == sub.varEnv.end() ) {
     
    167159        } else {
    168160                subCount++;
    169                 delete nameExpr;
    170                 return i->second->clone();
    171         } // if
    172 }
    173 
    174 void TypeSubstitution::Substituter::premutate( Type * type ) {
     161                return i->second;
     162        } // if
     163}
     164
     165void TypeSubstitution::Substituter::previsit( const ParameterizedType * ptype ) {
    175166        GuardValue( boundVars );
    176167        // bind type variables from forall-qualifiers
    177168        if ( freeOnly ) {
    178                 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
    179                         boundVars.insert( (*tyvar)->name );
     169                for ( const TypeDecl * tyvar : ptype->forall ) {
     170                                boundVars.insert( tyvar->name );
    180171                } // for
    181172        } // if
    182173}
    183174
    184 template< typename TypeClass >
    185 void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) {
     175void TypeSubstitution::Substituter::handleAggregateType( const ReferenceToType * type ) {
    186176        GuardValue( boundVars );
    187177        // bind type variables from forall-qualifiers
    188178        if ( freeOnly ) {
    189                 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
    190                         boundVars.insert( (*tyvar)->name );
     179                for ( const TypeDecl * tyvar : type->forall ) {
     180                        boundVars.insert( tyvar->name );
    191181                } // for
    192182                // bind type variables from generic type instantiations
    193                 std::list< TypeDecl* > *baseParameters = type->get_baseParameters();
    194                 if ( baseParameters && ! type->parameters.empty() ) {
    195                         for ( std::list< TypeDecl* >::const_iterator tyvar = baseParameters->begin(); tyvar != baseParameters->end(); ++tyvar ) {
    196                                 boundVars.insert( (*tyvar)->name );
    197                         } // for
    198                 } // if
    199         } // if
    200 }
    201 
    202 void TypeSubstitution::Substituter::premutate( StructInstType * aggregateUseType ) {
     183                if ( auto decl = type->aggr() ) {
     184                        if ( ! type->params.empty() ) {
     185                                for ( const TypeDecl * tyvar : decl->params ) {
     186                                        boundVars.insert( tyvar->name );
     187                                } // for
     188                        } // if
     189                }
     190        } // if
     191}
     192
     193void TypeSubstitution::Substituter::previsit( const StructInstType * aggregateUseType ) {
    203194        handleAggregateType( aggregateUseType );
    204195}
    205196
    206 void TypeSubstitution::Substituter::premutate( UnionInstType *aggregateUseType ) {
     197void TypeSubstitution::Substituter::previsit( const UnionInstType *aggregateUseType ) {
    207198        handleAggregateType( aggregateUseType );
    208199}
    209 
    210 #endif
    211200
    212201} // namespace ast
  • src/AST/TypeSubstitution.hpp

    r849720f r4a60488  
    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
     
    155161                Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
    156162
    157 #if TIME_TO_CONVERT_PASSES
    158 
    159                 Type * postmutate( TypeInstType * aggregateUseType );
    160                 Expression * postmutate( NameExpr * nameExpr );
     163                const Type * postvisit( const TypeInstType * aggregateUseType );
     164                const Expr * postvisit( const NameExpr * nameExpr );
    161165
    162166                /// Records type variable bindings from forall-statements
    163                 void premutate( Type * type );
     167                void previsit( const ParameterizedType * type );
    164168                /// Records type variable bindings from forall-statements and instantiations of generic types
    165                 template< typename TypeClass > void handleAggregateType( TypeClass * type );
    166 
    167                 void premutate( StructInstType * aggregateUseType );
    168                 void premutate( UnionInstType * aggregateUseType );
    169 
    170 #endif
     169                void handleAggregateType( const ReferenceToType * type );
     170
     171                void previsit( const StructInstType * aggregateUseType );
     172                void previsit( const UnionInstType * aggregateUseType );
    171173
    172174                const TypeSubstitution & sub;
     
    179181
    180182template< typename SynTreeClass >
    181 int TypeSubstitution::apply( const SynTreeClass *& input ) const {
     183TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::apply( const SynTreeClass * input ) const {
    182184        assert( input );
    183185        Pass<Substituter> sub( *this, false );
    184186        input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
    185 ///     std::cerr << "substitution result is: ";
    186 ///     newType->print( std::cerr );
    187 ///     std::cerr << std::endl;
    188         return sub.pass.subCount;
     187        return { input, sub.pass.subCount };
    189188}
    190189
    191190template< typename SynTreeClass >
    192 int TypeSubstitution::applyFree( const SynTreeClass *& input ) const {
     191TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::applyFree( const SynTreeClass * input ) const {
    193192        assert( input );
    194193        Pass<Substituter> sub( *this, true );
    195194        input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
    196 ///     std::cerr << "substitution result is: ";
    197 ///     newType->print( std::cerr );
    198 ///     std::cerr << std::endl;
    199         return sub.pass.subCount;
     195        return { input, sub.pass.subCount };
    200196}
    201197
  • src/AST/module.mk

    r849720f r4a60488  
    2222        AST/DeclReplacer.cpp \
    2323        AST/Expr.cpp \
     24        AST/ForallSubstitutionTable.cpp \
    2425        AST/GenericSubstitution.cpp \
    2526        AST/Init.cpp \
  • src/Common/ScopedMap.h

    r849720f r4a60488  
    249249
    250250        /// Gets the note at the given scope
     251        Note& getNote() { return scopes.back().note; }
     252        const Note& getNote() const { return scopes.back().note; }
    251253        Note& getNote( size_type i ) { return scopes[i].note; }
    252254        const Note& getNote( size_type i ) const { return scopes[i].note; }
  • src/Makefile.in

    r849720f r4a60488  
    169169        AST/Convert.$(OBJEXT) AST/Decl.$(OBJEXT) \
    170170        AST/DeclReplacer.$(OBJEXT) AST/Expr.$(OBJEXT) \
     171        AST/ForallSubstitutionTable.$(OBJEXT) \
    171172        AST/GenericSubstitution.$(OBJEXT) AST/Init.$(OBJEXT) \
    172173        AST/LinkageSpec.$(OBJEXT) AST/Node.$(OBJEXT) \
     
    590591        AST/DeclReplacer.cpp \
    591592        AST/Expr.cpp \
     593        AST/ForallSubstitutionTable.cpp \
    592594        AST/GenericSubstitution.cpp \
    593595        AST/Init.cpp \
     
    766768        AST/$(DEPDIR)/$(am__dirstamp)
    767769AST/Expr.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
     770AST/ForallSubstitutionTable.$(OBJEXT): AST/$(am__dirstamp) \
     771        AST/$(DEPDIR)/$(am__dirstamp)
    768772AST/GenericSubstitution.$(OBJEXT): AST/$(am__dirstamp) \
    769773        AST/$(DEPDIR)/$(am__dirstamp)
     
    12211225@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/DeclReplacer.Po@am__quote@
    12221226@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Expr.Po@am__quote@
     1227@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/ForallSubstitutionTable.Po@am__quote@
    12231228@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/GenericSubstitution.Po@am__quote@
    12241229@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Init.Po@am__quote@
  • src/ResolvExpr/AdjustExprType.cc

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

    r849720f r4a60488  
    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

    r849720f r4a60488  
    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 );
     
    370370                                                        // push empty tuple expression
    371371                                                        newResult.parent = i;
    372                                                         std::vector< ast::ptr< ast::Expr > > emptyList;
    373                                                         newResult.expr =
    374                                                                 new ast::TupleExpr{ CodeLocation{}, move( emptyList ) };
     372                                                        newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} };
    375373                                                        argType = newResult.expr->result;
    376374                                                } else {
     
    400398
    401399                                                // check unification for ttype before adding to final
    402                                                 if ( 
    403                                                         unify( 
     400                                                if (
     401                                                        unify(
    404402                                                                ttype, argType, newResult.env, newResult.need, newResult.have,
    405                                                                 newResult.open, symtab ) 
     403                                                                newResult.open, symtab )
    406404                                                ) {
    407405                                                        finalResults.emplace_back( move( newResult ) );
     
    424422                                                if ( expl.exprs.empty() ) {
    425423                                                        results.emplace_back(
    426                                                                 results[i], move( env ), copy( results[i].need ), 
     424                                                                results[i], move( env ), copy( results[i].need ),
    427425                                                                copy( results[i].have ), move( open ), nextArg + 1, expl.cost );
    428                                                        
     426
    429427                                                        continue;
    430428                                                }
     
    432430                                                // add new result
    433431                                                results.emplace_back(
    434                                                         i, expl.exprs.front(), move( env ), copy( results[i].need ), 
    435                                                         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,
    436434                                                        expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    437435                                        }
     
    479477
    480478                                        results.emplace_back(
    481                                                 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 
     479                                                i, expr, move( env ), move( need ), move( have ), move( open ), nextArg,
    482480                                                nTuples, Cost::zero, nextExpl, results[i].explAlt );
    483481                                }
     
    495493                                        if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {
    496494                                                results.emplace_back(
    497                                                         i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 
     495                                                        i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ),
    498496                                                        move( need ), move( have ), move( open ), nextArg, nTuples );
    499497                                        }
     
    517515                                if ( expl.exprs.empty() ) {
    518516                                        results.emplace_back(
    519                                                 results[i], move( env ), move( need ), move( have ), move( open ), 
     517                                                results[i], move( env ), move( need ), move( have ), move( open ),
    520518                                                nextArg + 1, expl.cost );
    521                                        
     519
    522520                                        continue;
    523521                                }
     
    539537                                        // add new result
    540538                                        results.emplace_back(
    541                                                 i, expr, move( env ), move( need ), move( have ), move( open ), 
     539                                                i, expr, move( env ), move( need ), move( have ), move( open ),
    542540                                                nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    543541                                }
     
    548546                genStart = genEnd;
    549547
    550                 return genEnd != results.size();
     548                return genEnd != results.size();  // were any new results added?
    551549        }
    552550
    553551        /// Generate a cast expression from `arg` to `toType`
    554         const ast::Expr * restructureCast( 
     552        const ast::Expr * restructureCast(
    555553                ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast
    556554        ) {
    557                 if ( 
    558                         arg->result->size() > 1 
    559                         && ! toType->isVoid() 
    560                         && ! dynamic_cast< const ast::ReferenceType * >( toType ) 
     555                if (
     556                        arg->result->size() > 1
     557                        && ! toType->isVoid()
     558                        && ! dynamic_cast< const ast::ReferenceType * >( toType )
    561559                ) {
    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 
     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
    566564                        // UniqueExpr ensures that the side effects will still be produced)
    567565                        if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {
    568                                 // 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
    569567                                // the expression
    570568                                arg = new ast::UniqueExpr{ arg->location, arg };
     
    574572                                // cast each component
    575573                                ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i };
    576                                 components.emplace_back( 
     574                                components.emplace_back(
    577575                                        restructureCast( idx, toType->getComponent( i ), isGenerated ) );
    578576                        }
     
    594592
    595593        /// Actually visits expressions to find their candidate interpretations
    596         struct Finder final : public ast::WithShortCircuiting {
     594        class Finder final : public ast::WithShortCircuiting {
     595                const ast::SymbolTable & symtab;
     596        public:
    597597                CandidateFinder & selfFinder;
    598                 const ast::SymbolTable & symtab;
    599598                CandidateList & candidates;
    600599                const ast::TypeEnvironment & tenv;
     
    602601
    603602                Finder( CandidateFinder & f )
    604                 : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
     603                : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
    605604                  targetType( f.targetType ) {}
    606                
     605
    607606                void previsit( const ast::Node * ) { visit_children = false; }
    608607
     
    639638
    640639                /// Completes a function candidate with arguments located
    641                 void validateFunctionCandidate( 
    642                         const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 
    643                         CandidateList & out 
     640                void validateFunctionCandidate(
     641                        const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,
     642                        CandidateList & out
    644643                ) {
    645                         ast::ApplicationExpr * appExpr = 
     644                        ast::ApplicationExpr * appExpr =
    646645                                new ast::ApplicationExpr{ func->expr->location, func->expr };
    647646                        // sum cost and accumulate arguments
     
    657656                        appExpr->args = move( vargs );
    658657                        // build and validate new candidate
    659                         auto newCand = 
     658                        auto newCand =
    660659                                std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );
    661660                        PRINT(
     
    669668                /// Builds a list of candidates for a function, storing them in out
    670669                void makeFunctionCandidates(
    671                         const CandidateRef & func, const ast::FunctionType * funcType, 
     670                        const CandidateRef & func, const ast::FunctionType * funcType,
    672671                        const ExplodedArgs_new & args, CandidateList & out
    673672                ) {
     
    676675                        ast::TypeEnvironment funcEnv{ func->env };
    677676                        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
     677                        // add all type variables as open variables now so that those not used in the
     678                        // parameter list are still considered open
    680679                        funcEnv.add( funcType->forall );
    681680
     
    683682                                // attempt to narrow based on expected target type
    684683                                const ast::Type * returnType = funcType->returns.front()->get_type();
    685                                 if ( ! unify( 
    686                                         returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 
     684                                if ( ! unify(
     685                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
    687686                                ) {
    688687                                        // unification failed, do not pursue this candidate
     
    698697                        for ( const ast::DeclWithType * param : funcType->params ) {
    699698                                auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
    700                                 // 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
    701700                                // matches
    702                                 if ( ! instantiateArgument( 
     701                                if ( ! instantiateArgument(
    703702                                        obj->type, obj->init, args, results, genStart, symtab ) ) return;
    704703                        }
     
    750749                                                        if ( expl.exprs.empty() ) {
    751750                                                                results.emplace_back(
    752                                                                         results[i], move( env ), copy( results[i].need ), 
    753                                                                         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,
    754753                                                                        expl.cost );
    755754
     
    760759                                                        results.emplace_back(
    761760                                                                i, expl.exprs.front(), move( env ), copy( results[i].need ),
    762                                                                 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 
     761                                                                copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost,
    763762                                                                expl.exprs.size() == 1 ? 0 : 1, j );
    764763                                                }
     
    780779                /// Adds implicit struct-conversions to the alternative list
    781780                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 
     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
    784783                        // base type to treat the aggregate as the referenced value
    785784                        ast::ptr< ast::Expr > aggrExpr( cand->expr );
    786785                        ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;
    787786                        cand->env.apply( aggrType );
    788                        
     787
    789788                        if ( aggrType.as< ast::ReferenceType >() ) {
    790789                                aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };
     
    799798
    800799                /// 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 
     800                void addAggMembers(
     801                        const ast::ReferenceToType * aggrInst, const ast::Expr * expr,
     802                        const Candidate & cand, const Cost & addedCost, const std::string & name
    804803                ) {
    805804                        for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {
    806805                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );
    807                                 CandidateRef newCand = std::make_shared<Candidate>( 
     806                                CandidateRef newCand = std::make_shared<Candidate>(
    808807                                        cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
    809                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     808                                // add anonymous member interpretations whenever an aggregate value type is seen
    810809                                // as a member expression
    811810                                addAnonConversions( newCand );
     
    815814
    816815                /// 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 
     816                void addTupleMembers(
     817                        const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,
     818                        const Cost & addedCost, const ast::Expr * member
    820819                ) {
    821820                        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 
     821                                // get the value of the constant expression as an int, must be between 0 and the
    823822                                // length of the tuple to have meaning
    824823                                long long val = constantExpr->intValue();
    825824                                if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    826825                                        addCandidate(
    827                                                 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 
     826                                                cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },
    828827                                                addedCost );
    829828                                }
     
    837836                        if ( funcFinder.candidates.empty() ) return;
    838837
    839                         std::vector< CandidateFinder > argCandidates = 
     838                        std::vector< CandidateFinder > argCandidates =
    840839                                selfFinder.findSubExprs( untypedExpr->args );
    841                        
     840
    842841                        // take care of possible tuple assignments
    843842                        // if not tuple assignment, handled as normal function call
     
    877876                                                if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    878877                                                        CandidateRef newFunc{ new Candidate{ *func } };
    879                                                         newFunc->expr = 
     878                                                        newFunc->expr =
    880879                                                                referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    881880                                                        makeFunctionCandidates( newFunc, function, argExpansions, found );
    882881                                                }
    883                                         } else if ( 
    884                                                 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 
     882                                        } else if (
     883                                                auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
    885884                                        ) {
    886885                                                if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) {
    887886                                                        if ( auto function = clz->bound.as< ast::FunctionType >() ) {
    888887                                                                CandidateRef newFunc{ new Candidate{ *func } };
    889                                                                 newFunc->expr = 
     888                                                                newFunc->expr =
    890889                                                                        referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    891890                                                                makeFunctionCandidates( newFunc, function, argExpansions, found );
     
    901900                                std::vector< ExplodedArg > funcE;
    902901                                funcE.reserve( funcFinder.candidates.size() );
    903                                 for ( const CandidateRef & func : funcFinder ) { 
     902                                for ( const CandidateRef & func : funcFinder ) {
    904903                                        funcE.emplace_back( *func, symtab );
    905904                                }
     
    913912                                                        if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    914913                                                                CandidateRef newOp{ new Candidate{ *op} };
    915                                                                 newOp->expr = 
     914                                                                newOp->expr =
    916915                                                                        referenceToRvalueConversion( newOp->expr, newOp->cost );
    917916                                                                makeFunctionCandidates( newOp, function, argExpansions, found );
     
    922921                        }
    923922
    924                         // 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
    925924                        // candidates
    926925                        if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
     
    934933                                        auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
    935934                                        auto function = pointer->base.strict_as< ast::FunctionType >();
    936                                        
     935
    937936                                        std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;
    938937                                        std::cerr << "parameters are:" << std::endl;
     
    957956                        promoteCvtCost( winners );
    958957
    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 
     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
    961960                        // `findMinCost`, since anon conversions are never the cheapest
    962961                        for ( const CandidateRef & c : winners ) {
     
    966965
    967966                        if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
    968                                 // 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
    969968                                // will sometimes succeed when it wouldn't with a target type binding.
    970969                                // For example:
     
    10161015                                cand->env.extractOpenVars( open );
    10171016
    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 
     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
    10211020                                // has fewer results than there are types to cast to.
    10221021                                int discardedValues = cand->expr->result->size() - toType->size();
     
    10371036                                        // count one safe conversion for each value that is thrown away
    10381037                                        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, 
     1038                                        CandidateRef newCand = std::make_shared<Candidate>(
     1039                                                restructureCast( cand->expr, toType, castExpr->isGenerated ),
     1040                                                copy( cand->env ), move( open ), move( need ), cand->cost,
    10421041                                                cand->cost + thisCost );
    10431042                                        inferParameters( newCand, matches );
     
    10571056                        finder.find( castExpr->arg, ResolvMode::withoutPrune() );
    10581057                        for ( CandidateRef & r : finder.candidates ) {
    1059                                 addCandidate( 
    1060                                         *r, 
     1058                                addCandidate(
     1059                                        *r,
    10611060                                        new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
    10621061                        }
     
    10671066                        aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    10681067                        for ( CandidateRef & agg : aggFinder.candidates ) {
    1069                                 // 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
    10701069                                // base type to treat the aggregate as the referenced value
    10711070                                Cost addedCost = Cost::zero;
     
    10741073                                // find member of the given type
    10751074                                if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {
    1076                                         addAggMembers( 
     1075                                        addAggMembers(
    10771076                                                structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10781077                                } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {
    1079                                         addAggMembers( 
     1078                                        addAggMembers(
    10801079                                                unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10811080                                } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {
     
    10971096
    10981097                                CandidateRef newCand = std::make_shared<Candidate>(
    1099                                         newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 
     1098                                        newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
    11001099                                        cost );
    11011100                                PRINT(
     
    11071106                                        std::cerr << std::endl;
    11081107                                )
    1109                                 newCand->expr = ast::mutate_field( 
    1110                                         newCand->expr.get(), &ast::Expr::result, 
     1108                                newCand->expr = ast::mutate_field(
     1109                                        newCand->expr.get(), &ast::Expr::result,
    11111110                                        renameTyVars( newCand->expr->result ) );
    1112                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     1111                                // add anonymous member interpretations whenever an aggregate value type is seen
    11131112                                // as a name expression
    11141113                                addAnonConversions( newCand );
     
    11201119                        // not sufficient to just pass `variableExpr` here, type might have changed since
    11211120                        // creation
    1122                         addCandidate( 
     1121                        addCandidate(
    11231122                                new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
    11241123                }
     
    11301129                void postvisit( const ast::SizeofExpr * sizeofExpr ) {
    11311130                        if ( sizeofExpr->type ) {
    1132                                 addCandidate( 
    1133                                         new ast::SizeofExpr{ 
    1134                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 
     1131                                addCandidate(
     1132                                        new ast::SizeofExpr{
     1133                                                sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
    11351134                                        tenv );
    11361135                        } else {
     
    11411140                                CandidateList winners = findMinCost( finder.candidates );
    11421141                                if ( winners.size() != 1 ) {
    1143                                         SemanticError( 
     1142                                        SemanticError(
    11441143                                                sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );
    11451144                                }
     
    11541153                void postvisit( const ast::AlignofExpr * alignofExpr ) {
    11551154                        if ( alignofExpr->type ) {
    1156                                 addCandidate( 
    1157                                         new ast::AlignofExpr{ 
    1158                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 
     1155                                addCandidate(
     1156                                        new ast::AlignofExpr{
     1157                                                alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
    11591158                                        tenv );
    11601159                        } else {
     
    11651164                                CandidateList winners = findMinCost( finder.candidates );
    11661165                                if ( winners.size() != 1 ) {
    1167                                         SemanticError( 
     1166                                        SemanticError(
    11681167                                                alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );
    11691168                                }
     
    11721171                                choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    11731172                                choice->cost = Cost::zero;
    1174                                 addCandidate( 
     1173                                addCandidate(
    11751174                                        *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );
    11761175                        }
     
    11851184                        for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {
    11861185                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );
    1187                                 addCandidate( 
     1186                                addCandidate(
    11881187                                        new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );
    11891188                        }
     
    12181217
    12191218                                        addCandidate(
    1220                                                 new ast::LogicalExpr{ 
     1219                                                new ast::LogicalExpr{
    12211220                                                        logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
    12221221                                                move( env ), move( open ), move( need ), r1->cost + r2->cost );
     
    12561255                                                ast::AssertionSet have;
    12571256
    1258                                                 // unify true and false results, then infer parameters to produce new 
     1257                                                // unify true and false results, then infer parameters to produce new
    12591258                                                // candidates
    12601259                                                ast::ptr< ast::Type > common;
    1261                                                 if ( 
    1262                                                         unify( 
    1263                                                                 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 
    1264                                                                 common ) 
     1260                                                if (
     1261                                                        unify(
     1262                                                                r2->expr->result, r3->expr->result, env, need, have, open, symtab,
     1263                                                                common )
    12651264                                                ) {
    12661265                                                        // generate typed expression
    1267                                                         ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 
     1266                                                        ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{
    12681267                                                                conditionalExpr->location, r1->expr, r2->expr, r3->expr };
    12691268                                                        newExpr->result = common ? common : r2->expr->result;
    12701269                                                        // convert both options to result type
    12711270                                                        Cost cost = r1->cost + r2->cost + r3->cost;
    1272                                                         newExpr->arg2 = computeExpressionConversionCost( 
     1271                                                        newExpr->arg2 = computeExpressionConversionCost(
    12731272                                                                newExpr->arg2, newExpr->result, symtab, env, cost );
    12741273                                                        newExpr->arg3 = computeExpressionConversionCost(
     
    12871286                        ast::TypeEnvironment env{ tenv };
    12881287                        ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
    1289                        
     1288
    12901289                        CandidateFinder finder2{ symtab, env };
    12911290                        finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
     
    13301329
    13311330                                        ast::ptr< ast::Type > common;
    1332                                         if ( 
    1333                                                 unify( 
    1334                                                         r1->expr->result, r2->expr->result, env, need, have, open, symtab, 
    1335                                                         common ) 
     1331                                        if (
     1332                                                unify(
     1333                                                        r1->expr->result, r2->expr->result, env, need, have, open, symtab,
     1334                                                        common )
    13361335                                        ) {
    13371336                                                // generate new expression
    1338                                                 ast::RangeExpr * newExpr = 
     1337                                                ast::RangeExpr * newExpr =
    13391338                                                        new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
    13401339                                                newExpr->result = common ? common : r1->expr->result;
    13411340                                                // add candidate
    13421341                                                CandidateRef newCand = std::make_shared<Candidate>(
    1343                                                         newExpr, move( env ), move( open ), move( need ), 
     1342                                                        newExpr, move( env ), move( open ), move( need ),
    13441343                                                        r1->cost + r2->cost );
    13451344                                                inferParameters( newCand, candidates );
     
    13501349
    13511350                void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
    1352                         std::vector< CandidateFinder > subCandidates = 
     1351                        std::vector< CandidateFinder > subCandidates =
    13531352                                selfFinder.findSubExprs( tupleExpr->exprs );
    13541353                        std::vector< CandidateList > possibilities;
     
    13701369
    13711370                                addCandidate(
    1372                                         new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 
     1371                                        new ast::TupleExpr{ tupleExpr->location, move( exprs ) },
    13731372                                        move( env ), move( open ), move( need ), sumCost( subs ) );
    13741373                        }
     
    14121411                                toType = SymTab::validateType( initExpr->location, toType, symtab );
    14131412                                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. 
     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.
    14171416                                CandidateFinder finder{ symtab, tenv, toType };
    14181417                                finder.find( initExpr->expr, ResolvMode::withAdjustment() );
     
    14261425                                        )
    14271426
    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 
     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
    14311430                                        // if it has fewer results than there are types to cast to.
    14321431                                        int discardedValues = cand->expr->result->size() - toType->size();
     
    14361435                                        unify( toType, cand->expr->result, env, need, have, open, symtab );
    14371436                                        Cost thisCost = castCost( cand->expr->result, toType, symtab, env );
    1438                                        
     1437
    14391438                                        if ( thisCost != Cost::infinity ) {
    14401439                                                // count one safe conversion for each value that is thrown away
    14411440                                                thisCost.incSafe( discardedValues );
    1442                                                 CandidateRef newCand = std::make_shared<Candidate>( 
    1443                                                         new ast::InitExpr{ 
    1444                                                                 initExpr->location, restructureCast( cand->expr, toType ), 
    1445                                                                 initAlt.designation }, 
     1441                                                CandidateRef newCand = std::make_shared<Candidate>(
     1442                                                        new ast::InitExpr{
     1443                                                                initExpr->location, restructureCast( cand->expr, toType ),
     1444                                                                initAlt.designation },
    14461445                                                        copy( cand->env ), move( open ), move( need ), cand->cost, thisCost );
    14471446                                                inferParameters( newCand, matches );
     
    14691468        };
    14701469
    1471         /// 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
    14721471        /// return type. Skips ambiguous candidates.
    14731472        CandidateList pruneCandidates( CandidateList & candidates ) {
     
    14861485                        {
    14871486                                ast::ptr< ast::Type > newType = candidate->expr->result;
     1487                                assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());
    14881488                                candidate->env.apply( newType );
    14891489                                mangleName = Mangle::mangle( newType );
     
    14941494                                if ( candidate->cost < found->second.candidate->cost ) {
    14951495                                        PRINT(
    1496                                                 std::cerr << "cost " << candidate->cost << " beats " 
     1496                                                std::cerr << "cost " << candidate->cost << " beats "
    14971497                                                        << found->second.candidate->cost << std::endl;
    14981498                                        )
     
    15001500                                        found->second = PruneStruct{ candidate };
    15011501                                } 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 
     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
    15041504                                        // that is at least as good
    15051505                                        if ( findDeletedExpr( candidate->expr ) ) {
     
    15151515                                } else {
    15161516                                        PRINT(
    1517                                                 std::cerr << "cost " << candidate->cost << " loses to " 
     1517                                                std::cerr << "cost " << candidate->cost << " loses to "
    15181518                                                        << found->second.candidate->cost << std::endl;
    15191519                                        )
     
    15301530
    15311531                        CandidateRef cand = target.second.candidate;
    1532                        
     1532
    15331533                        ast::ptr< ast::Type > newResult = cand->expr->result;
    15341534                        cand->env.applyFree( newResult );
    15351535                        cand->expr = ast::mutate_field(
    15361536                                cand->expr.get(), &ast::Expr::result, move( newResult ) );
    1537                        
     1537
    15381538                        out.emplace_back( cand );
    15391539                }
     
    15581558                std::vector< std::string > errors;
    15591559                for ( CandidateRef & candidate : candidates ) {
    1560                         satisfyAssertions( candidate, symtab, satisfied, errors );
     1560                        satisfyAssertions( candidate, localSyms, satisfied, errors );
    15611561                }
    15621562
     
    15831583
    15841584                CandidateList pruned = pruneCandidates( candidates );
    1585                
     1585
    15861586                if ( mode.failFast && pruned.empty() ) {
    15871587                        std::ostringstream stream;
     
    16021602                )
    16031603                PRINT(
    1604                         std::cerr << "there are " << candidates.size() << " alternatives after elimination" 
     1604                        std::cerr << "there are " << candidates.size() << " alternatives after elimination"
    16051605                                << std::endl;
    16061606                )
    16071607        }
    16081608
    1609         // adjust types after pruning so that types substituted by pruneAlternatives are correctly 
     1609        // adjust types after pruning so that types substituted by pruneAlternatives are correctly
    16101610        // adjusted
    16111611        if ( mode.adjust ) {
    16121612                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 ) );
     1613                        r->expr = ast::mutate_field(
     1614                                r->expr.get(), &ast::Expr::result,
     1615                                adjustExprType( r->expr->result, r->env, localSyms ) );
    16161616                }
    16171617        }
     
    16251625}
    16261626
    1627 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 
    1628         const std::vector< ast::ptr< ast::Expr > > & xs 
     1627std::vector< CandidateFinder > CandidateFinder::findSubExprs(
     1628        const std::vector< ast::ptr< ast::Expr > > & xs
    16291629) {
    16301630        std::vector< CandidateFinder > out;
    16311631
    16321632        for ( const auto & x : xs ) {
    1633                 out.emplace_back( symtab, env );
     1633                out.emplace_back( localSyms, env );
    16341634                out.back().find( x, ResolvMode::withAdjustment() );
    1635                
     1635
    16361636                PRINT(
    16371637                        std::cerr << "findSubExprs" << std::endl;
  • src/ResolvExpr/CandidateFinder.hpp

    r849720f r4a60488  
    2828struct CandidateFinder {
    2929        CandidateList candidates;          ///< List of candidate resolutions
    30         const ast::SymbolTable & symtab;   ///< Symbol table to lookup candidates
     30        const ast::SymbolTable & localSyms;   ///< Symbol table to lookup candidates
    3131        const ast::TypeEnvironment & env;  ///< Substitutions performed in this resolution
    3232        ast::ptr< ast::Type > targetType;  ///< Target type for resolution
    3333
    3434        CandidateFinder(
    35                 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
     35                const ast::SymbolTable & syms, const ast::TypeEnvironment & env,
    3636                const ast::Type * tt = nullptr )
    37         : candidates(), symtab( symtab ), env( env ), targetType( tt ) {}
     37        : candidates(), localSyms( syms ), env( env ), targetType( tt ) {}
    3838
    3939        /// Fill candidates with feasible resolutions for `expr`
  • src/ResolvExpr/CommonType.cc

    r849720f r4a60488  
    939939                        ast::ptr< ast::Type > result;
    940940                        const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >();
    941                         const ast::ReferenceType * ref2 = type1.as< ast::ReferenceType >();
     941                        const ast::ReferenceType * ref2 = type2.as< ast::ReferenceType >();
    942942
    943943                        if ( depth1 > depth2 ) {
  • src/ResolvExpr/ConversionCost.cc

    r849720f r4a60488  
    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
     12// Last Modified On : Thr Jul  4 10:56:00 2019
    1313// Update Count     : 27
    1414//
     
    701701void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
    702702        (void)enumInstType;
    703         static const ast::BasicType integer( ast::BasicType::SignedInt );
    704         cost = costCalc( &integer, dst, symtab, env );
     703        static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
     704        cost = costCalc( integer, dst, symtab, env );
    705705        if ( cost < Cost::unsafe ) {
    706706                cost.incSafe();
     
    772772                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    773773                }
     774        } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
     775                cost = Cost::zero;
     776                // +1 for zero_t ->, +1 for disambiguation
     777                cost.incSafe( maxIntCost + 2 );
    774778        }
    775779}
     
    789793                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    790794                }
    791         } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
    792                 cost = Cost::zero;
    793                 cost.incSafe( maxIntCost + 2 );
    794795        }
    795796}
  • src/ResolvExpr/CurrentObject.cc

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

    r849720f r4a60488  
    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 ) {
  • src/ResolvExpr/RenameVars.cc

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

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

    r849720f r4a60488  
    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                                ) {
     
    11081108
    11091109                // set up and resolve expression cast to void
    1110                 ast::CastExpr * untyped = new ast::CastExpr{ expr };
     1110                ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
    11111111                CandidateRef choice = findUnfinishedKindExpression(
    11121112                        untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
     
    12471247        };
    12481248
    1249         void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) {
     1249        void resolve( std::list< ast::ptr< ast::Decl > >& translationUnit ) {
    12501250                ast::Pass< Resolver_new > resolver;
    12511251                accept_all( translationUnit, resolver );
     
    12811281                ast::ptr< ast::FunctionDecl > ret = functionDecl;
    12821282                for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {
    1283                         const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i];
     1283                        const ast::ptr< ast::DeclWithType > & d = functionDecl->type->params[i];
    12841284
    12851285                        if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {
     
    12981298                        }
    12991299                }
    1300                 return ret.get();
     1300                return ret.release();
    13011301        }
    13021302
     
    13211321                // in case we decide to allow nested enums
    13221322                GuardValue( inEnumDecl );
    1323                 inEnumDecl = false;
     1323                inEnumDecl = true;
    13241324        }
    13251325
  • src/ResolvExpr/SpecCost.cc

    r849720f r4a60488  
    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                        }
  • src/ResolvExpr/Unify.cc

    r849720f r4a60488  
    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);
    177171
    178172                return unifyExact(
    179                         newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     173                        env.apply( newFirst  ).node,
     174                        env.apply( newSecond ).node,
     175                        newEnv, need, have, open, noWiden(), symtab );
    180176        }
    181177
     
    326322
    327323        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;
    333324                AssertionSet::iterator i = assertions.find( assert );
    334325                if ( i != assertions.end() ) {
    335 ///     std::cerr << "found it!" << std::endl;
    336326                        i->second.isUsed = true;
    337327                } // if
     
    12021192                // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and
    12031193                // 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 );
     1194                ast::Type * t1 = shallowCopy(type1.get());
     1195                ast::Type * t2 = shallowCopy(type2.get());
     1196                t1->qualifiers = {};
     1197                t2->qualifiers = {};
     1198                ast::ptr< ast::Type > t1_(t1);
     1199                ast::ptr< ast::Type > t2_(t2);
    12071200
    12081201                if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
    1209                         t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
    1210 
    12111202                        // if exact unification on unqualified types, try to merge qualifiers
    12121203                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
    1213                                 common = type1;
    1214                                 reset_qualifiers( common, q1 | q2 );
     1204                                t1->qualifiers = q1 | q2;
     1205                                common = t1;
    12151206                                return true;
    12161207                        } else {
     
    12191210
    12201211                } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {
    1221                         t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
    1222 
    12231212                        // no exact unification, but common type
    1224                         reset_qualifiers( common, q1 | q2 );
     1213                        auto c = shallowCopy(common.get());
     1214                        c->qualifiers = q1 | q2;
     1215                        common = c;
    12251216                        return true;
    12261217                } else {
  • src/SymTab/Autogen.h

    r849720f r4a60488  
    2121
    2222#include "AST/Decl.hpp"
     23#include "AST/Eval.hpp"
    2324#include "AST/Expr.hpp"
    2425#include "AST/Init.hpp"
     
    264265                }
    265266
    266                 ast::ptr< ast::Expr > begin, end, cmp, update;
     267                ast::ptr< ast::Expr > begin, end;
     268                std::string cmp, update;
    267269
    268270                if ( forward ) {
     
    270272                        begin = ast::ConstantExpr::from_int( loc, 0 );
    271273                        end = array->dimension;
    272                         cmp = new ast::NameExpr{ loc, "?<?" };
    273                         update = new ast::NameExpr{ loc, "++?" };
     274                        cmp = "?<?";
     275                        update = "++?";
    274276                } else {
    275277                        // generate: for ( int i = N-1; i >= 0; --i )
    276                         begin = new ast::UntypedExpr{
    277                                 loc, new ast::NameExpr{ loc, "?-?" },
    278                                 { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } };
     278                        begin = ast::call(
     279                                loc, "?-?", array->dimension, ast::ConstantExpr::from_int( loc, 1 ) );
    279280                        end = ast::ConstantExpr::from_int( loc, 0 );
    280                         cmp = new ast::NameExpr{ loc, "?>=?" };
    281                         update = new ast::NameExpr{ loc, "--?" };
     281                        cmp = "?>=?";
     282                        update = "--?";
    282283                }
    283284
     
    285286                        loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },
    286287                        new ast::SingleInit{ loc, begin } };
    287                
    288                 ast::ptr< ast::Expr > cond = new ast::UntypedExpr{
    289                         loc, cmp, { new ast::VariableExpr{ loc, index }, end } };
    290                
    291                 ast::ptr< ast::Expr > inc = new ast::UntypedExpr{
    292                         loc, update, { new ast::VariableExpr{ loc, index } } };
    293                
    294                 ast::ptr< ast::Expr > dstIndex = new ast::UntypedExpr{
    295                         loc, new ast::NameExpr{ loc, "?[?]" },
    296                         { dstParam, new ast::VariableExpr{ loc, index } } };
     288                ast::ptr< ast::Expr > indexVar = new ast::VariableExpr{ loc, index };
     289               
     290                ast::ptr< ast::Expr > cond = ast::call( loc, cmp, indexVar, end );
     291               
     292                ast::ptr< ast::Expr > inc = ast::call( loc, update, indexVar );
     293               
     294                ast::ptr< ast::Expr > dstIndex = ast::call( loc, "?[?]", dstParam, indexVar );
    297295               
    298296                // srcParam must keep track of the array indices to build the source parameter and/or
    299297                // array list initializer
    300                 srcParam.addArrayIndex( new ast::VariableExpr{ loc, index }, array->dimension );
     298                srcParam.addArrayIndex( indexVar, array->dimension );
    301299
    302300                // for stmt's body, eventually containing call
     
    384382                if ( isUnnamedBitfield( obj ) ) return {};
    385383
    386                 ast::ptr< ast::Type > addCast = nullptr;
     384                ast::ptr< ast::Type > addCast;
    387385                if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
    388386                        assert( dstParam->result );
  • src/SynTree/Statement.h

    r849720f r4a60488  
    502502class ImplicitCtorDtorStmt : public Statement {
    503503  public:
    504         // Non-owned pointer to the constructor/destructor statement
     504        // the constructor/destructor call statement; owned here for a while, eventually transferred elsewhere
    505505        Statement * callStmt;
    506506
  • src/Tuples/Explode.cc

    r849720f r4a60488  
    129129                        for ( const ast::Expr * expr : tupleExpr->exprs ) {
    130130                                exprs.emplace_back( applyCast( expr, false ) );
    131                                 //exprs.emplace_back( ast::ptr< ast::Expr >( applyCast( expr, false ) ) );
    132131                        }
    133132                        if ( first ) {
  • src/Tuples/Explode.h

    r849720f r4a60488  
    210210                        }
    211211                        // Cast a reference away to a value-type to allow further explosion.
    212                         if ( dynamic_cast< const ast::ReferenceType *>( local->result.get() ) ) {
     212                        if ( local->result.as< ast::ReferenceType >() ) {
    213213                                local = new ast::CastExpr{ local, tupleType };
    214214                        }
     
    220220                                // delete idx;
    221221                        }
    222                         // delete local;
    223222                }
    224223        } else {
  • src/Tuples/TupleAssignment.cc

    r849720f r4a60488  
    465465                                        // resolve ctor/dtor for the new object
    466466                                        ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit(
    467                                                         InitTweak::genCtorInit( location, ret ), spotter.crntFinder.symtab );
     467                                                        InitTweak::genCtorInit( location, ret ), spotter.crntFinder.localSyms );
    468468                                        // remove environments from subexpressions of stmtExpr
    469469                                        ast::Pass< EnvRemover > rm{ env };
     
    560560                                        // resolve the cast expression so that rhsCand return type is bound by the cast
    561561                                        // type as needed, and transfer the resulting environment
    562                                         ResolvExpr::CandidateFinder finder{ spotter.crntFinder.symtab, env };
     562                                        ResolvExpr::CandidateFinder finder{ spotter.crntFinder.localSyms, env };
    563563                                        finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() );
    564564                                        assert( finder.candidates.size() == 1 );
     
    609609                                        // explode the LHS so that each field of a tuple-valued expr is assigned
    610610                                        ResolvExpr::CandidateList lhs;
    611                                         explode( *lhsCand, crntFinder.symtab, back_inserter(lhs), true );
     611                                        explode( *lhsCand, crntFinder.localSyms, back_inserter(lhs), true );
    612612                                        for ( ResolvExpr::CandidateRef & cand : lhs ) {
    613613                                                // each LHS value must be a reference - some come in with a cast, if not
     
    629629                                                        if ( isTuple( rhsCand->expr ) ) {
    630630                                                                // multiple assignment
    631                                                                 explode( *rhsCand, crntFinder.symtab, back_inserter(rhs), true );
     631                                                                explode( *rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
    632632                                                                matcher.reset(
    633633                                                                        new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
     
    648648                                                        // multiple assignment
    649649                                                        ResolvExpr::CandidateList rhs;
    650                                                         explode( rhsCand, crntFinder.symtab, back_inserter(rhs), true );
     650                                                        explode( rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
    651651                                                        matcher.reset(
    652652                                                                new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
     
    678678                                )
    679679
    680                                 ResolvExpr::CandidateFinder finder{ crntFinder.symtab, matcher->env };
     680                                ResolvExpr::CandidateFinder finder{ crntFinder.localSyms, matcher->env };
    681681
    682682                                try {
  • src/main.cc

    r849720f r4a60488  
    2929#include <string>                           // for char_traits, operator<<
    3030
     31#include "AST/Convert.hpp"
    3132#include "CompilationState.h"
    3233#include "../config.h"                      // for CFA_LIBDIR
     
    313314                } // if
    314315
    315                 assertTopLvalue( translationUnit );
    316 
    317                 PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
     316                // PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
     317                {
     318                        auto transUnit = convert( move( translationUnit ) );
     319                        PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
     320                        translationUnit = convert( move( transUnit ) );
     321                }
     322
    318323                if ( exprp ) {
    319324                        dump( translationUnit );
Note: See TracChangeset for help on using the changeset viewer.