Changes in / [057298e:7030dab]


Ignore:
Files:
7 added
1 deleted
47 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Attribute.hpp

    r057298e r7030dab  
    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/CVQualifiers.hpp

    r057298e r7030dab  
    2727                Restrict = 1 << 1,
    2828                Volatile = 1 << 2,
    29                 Lvalue   = 1 << 3,
    30                 Mutex    = 1 << 4,
    31                 Atomic   = 1 << 5,
    32                 NumQualifiers = 6
     29                Mutex    = 1 << 3,
     30                Atomic   = 1 << 4,
     31                NumQualifiers = 5
    3332        };
    3433
    3534        /// Mask for equivalence-preserving qualfiers
    36         enum { EquivQualifiers = ~(Restrict | Lvalue) };
     35        enum { EquivQualifiers = ~Restrict };
    3736
    3837        /// Underlying data for qualifiers
     
    4443                                bool is_restrict : 1;
    4544                                bool is_volatile : 1;
    46                                 bool is_lvalue   : 1;
    4745                                bool is_mutex    : 1;
    4846                                bool is_atomic   : 1;
  • src/AST/Convert.cpp

    r057298e r7030dab  
    620620
    621621                tgt->result = get<Type>().accept1(src->result);
     622                // Unconditionally use a clone of the result type.
     623                // We know this will leak some objects: much of the immediate conversion result.
     624                // In some cases, using the conversion result directly gives unintended object sharing.
     625                // A parameter (ObjectDecl, a child of a FunctionType) is shared by the weak-ref cache.
     626                // But tgt->result must be fully owned privately by tgt.
     627                // Applying these conservative copies here means
     628                // - weak references point at the declaration's copy, not these expr.result copies (good)
     629                // - we copy more objects than really needed (bad, tolerated)
     630                if (tgt->result) {
     631                        tgt->result = tgt->result->clone();
     632                }
    622633                return visitBaseExpr_skipResultType(src, tgt);
    623634        }
     
    21172128                                old->location,
    21182129                                GET_ACCEPT_1(member, DeclWithType),
    2119                                 GET_ACCEPT_1(aggregate, Expr)
     2130                                GET_ACCEPT_1(aggregate, Expr),
     2131                                ast::MemberExpr::NoOpConstructionChosen
    21202132                        )
    21212133                );
  • src/AST/Decl.cpp

    r057298e r7030dab  
    5050
    5151const Type * FunctionDecl::get_type() const { return type.get(); }
    52 void FunctionDecl::set_type(Type * t) { type = strict_dynamic_cast< FunctionType* >( t ); }
     52void FunctionDecl::set_type( const Type * t ) {
     53        type = strict_dynamic_cast< const FunctionType * >( t );
     54}
    5355
    5456// --- TypeDecl
  • src/AST/Decl.hpp

    r057298e r7030dab  
    3333
    3434// Must be included in *all* AST classes; should be #undef'd at the end of the file
    35 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     35#define MUTATE_FRIEND \
     36    template<typename node_t> friend node_t * mutate(const node_t * node); \
     37        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3638
    3739namespace ast {
     
    8890        virtual const Type * get_type() const = 0;
    8991        /// Set type of this declaration. May be verified by subclass
    90         virtual void set_type(Type *) = 0;
     92        virtual void set_type( const Type * ) = 0;
    9193
    9294        const DeclWithType * accept( Visitor & v ) const override = 0;
     
    111113
    112114        const Type* get_type() const override { return type; }
    113         void set_type( Type * ty ) override { type = ty; }
     115        void set_type( const Type * ty ) override { type = ty; }
    114116
    115117        const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
     
    133135
    134136        const Type * get_type() const override;
    135         void set_type(Type * t) override;
     137        void set_type( const Type * t ) override;
    136138
    137139        bool has_body() const { return stmts; }
     
    150152        std::vector<ptr<DeclWithType>> assertions;
    151153
    152         NamedTypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
    153                 Type* b, Linkage::Spec spec = Linkage::Cforall )
     154        NamedTypeDecl(
     155                const CodeLocation & loc, const std::string & name, Storage::Classes storage,
     156                const Type * b, Linkage::Spec spec = Linkage::Cforall )
    154157        : Decl( loc, name, storage, spec ), base( b ), params(), assertions() {}
    155158
     
    186189        };
    187190
    188         TypeDecl( const CodeLocation & loc, const std::string & name, Storage::Classes storage, Type * b,
    189                           Kind k, bool s, Type * i = nullptr )
    190                 : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == Ttype || s ),
    191                 init( i ) {}
     191        TypeDecl(
     192                const CodeLocation & loc, const std::string & name, Storage::Classes storage,
     193                const Type * b, TypeVar::Kind k, bool s, const Type * i = nullptr )
     194        : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeVar::Ttype || s ),
     195          init( i ) {}
    192196
    193197        const char * typeString() const override;
  • src/AST/Expr.cpp

    r057298e r7030dab  
    2020#include <vector>
    2121
     22#include "Copy.hpp"                // for shallowCopy
     23#include "Eval.hpp"                // for call
    2224#include "GenericSubstitution.hpp"
     25#include "LinkageSpec.hpp"
    2326#include "Stmt.hpp"
    2427#include "Type.hpp"
     
    2730#include "Common/SemanticError.h"
    2831#include "GenPoly/Lvalue.h"        // for referencesPermissable
    29 #include "InitTweak/InitTweak.h"   // for getPointerBase
     32#include "InitTweak/InitTweak.h"   // for getFunction, getPointerBase
    3033#include "ResolvExpr/typeops.h"    // for extractResultType
    3134#include "Tuples/Tuples.h"         // for makeTupleType
    3235
    3336namespace ast {
     37
     38namespace {
     39        std::set<std::string> const lvalueFunctionNames = {"*?", "?[?]"};
     40}
     41
     42// --- Expr
     43bool Expr::get_lvalue() const {
     44        return false;
     45}
    3446
    3547// --- ApplicationExpr
     
    4658}
    4759
     60bool ApplicationExpr::get_lvalue() const {
     61        if ( const DeclWithType * func = InitTweak::getFunction( this ) ) {
     62                return func->linkage == Linkage::Intrinsic && lvalueFunctionNames.count( func->name );
     63        }
     64        return false;
     65}
     66
    4867// --- UntypedExpr
    4968
     
    5170        assert( arg );
    5271
    53         UntypedExpr * ret = new UntypedExpr{
    54                 loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } }
    55         };
     72        UntypedExpr * ret = call( loc, "*?", arg );
    5673        if ( const Type * ty = arg->result ) {
    5774                const Type * base = InitTweak::getPointerBase( ty );
     
    6582                        // base type
    6683                        ret->result = base;
    67                         add_qualifiers( ret->result, CV::Lvalue );
    6884                }
    6985        }
    7086        return ret;
     87}
     88
     89bool UntypedExpr::get_lvalue() const {
     90        std::string fname = InitTweak::getFunctionName( this );
     91        return lvalueFunctionNames.count( fname );
    7192}
    7293
     
    7495        assert( lhs && rhs );
    7596
    76         UntypedExpr * ret = new UntypedExpr{
    77                 loc, new NameExpr{loc, "?=?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ lhs }, ptr<Expr>{ rhs } }
    78         };
     97        UntypedExpr * ret = call( loc, "?=?", lhs, rhs );
    7998        if ( lhs->result && rhs->result ) {
    8099                // if both expressions are typed, assumes that this assignment is a C bitwise assignment,
     
    108127AddressExpr::AddressExpr( const CodeLocation & loc, const Expr * a ) : Expr( loc ), arg( a ) {
    109128        if ( arg->result ) {
    110                 if ( arg->result->is_lvalue() ) {
     129                if ( arg->get_lvalue() ) {
    111130                        // lvalue, retains all levels of reference, and gains a pointer inside the references
    112131                        Type * res = addrType( arg->result );
    113                         res->set_lvalue( false ); // result of & is never an lvalue
    114132                        result = res;
    115133                } else {
     
    118136                                        dynamic_cast< const ReferenceType * >( arg->result.get() ) ) {
    119137                                Type * res = addrType( refType->base );
    120                                 res->set_lvalue( false ); // result of & is never an lvalue
    121138                                result = res;
    122139                        } else {
     
    139156: Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {}
    140157
     158bool CastExpr::get_lvalue() const {
     159        // This is actually wrong by C, but it works with our current set-up.
     160        return arg->get_lvalue();
     161}
     162
    141163// --- KeywordCastExpr
    142164
    143165const char * KeywordCastExpr::targetString() const {
    144166        return AggregateDecl::aggrString( target );
     167}
     168
     169// --- UntypedMemberExpr
     170
     171bool UntypedMemberExpr::get_lvalue() const {
     172        return aggregate->get_lvalue();
    145173}
    146174
     
    153181        assert( aggregate->result );
    154182
    155         // take ownership of member type
    156         result = mem->get_type();
     183        // Deep copy on result type avoids mutation on transitively multiply referenced object.
     184        //
     185        // Example, adapted from parts of builtins and bootloader:
     186        //
     187        // forall(dtype T)
     188        // struct __Destructor {
     189        //   T * object;
     190        //   void (*dtor)(T *);
     191        // };
     192        //
     193        // forall(dtype S)
     194        // void foo(__Destructor(S) &d) {
     195        //   if (d.dtor) {  // here
     196        //   }
     197        // }
     198        //
     199        // Let e be the "d.dtor" guard espression, which is MemberExpr after resolve.  Let d be the
     200        // declaration of member __Destructor.dtor (an ObjectDecl), as accessed via the top-level
     201        // declaration of __Destructor.  Consider the types e.result and d.type.  In the old AST, one
     202        // is a clone of the other.  Ordinary new-AST use would set them up as a multiply-referenced
     203        // object.
     204        //
     205        // e.result: PointerType
     206        // .base: FunctionType
     207        // .params.front(): ObjectDecl, the anonymous parameter of type T*
     208        // .type: PointerType
     209        // .base: TypeInstType
     210        // let x = that
     211        // let y = similar, except start from d.type
     212        //
     213        // Consider two code lines down, genericSubstitution(...).apply(result).
     214        //
     215        // Applying this chosen-candidate's type substitution means modifying x, substituting
     216        // S for T.  This mutation should affect x and not y.
     217
     218        result = deepCopy(mem->get_type());
     219
    157220        // substitute aggregate generic parameters into member type
    158221        genericSubstitution( aggregate->result ).apply( result );
    159         // ensure lvalue and appropriate restrictions from aggregate type
    160         add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue );
     222        // ensure appropriate restrictions from aggregate type
     223        add_qualifiers( result, aggregate->result->qualifiers );
     224}
     225
     226MemberExpr::MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
     227    MemberExpr::NoOpConstruction overloadSelector )
     228: Expr( loc ), member( mem ), aggregate( agg ) {
     229        assert( member );
     230        assert( aggregate );
     231        assert( aggregate->result );
     232        (void) overloadSelector;
     233}
     234
     235bool MemberExpr::get_lvalue() const {
     236        // This is actually wrong by C, but it works with our current set-up.
     237        return true;
    161238}
    162239
     
    170247        assert( var );
    171248        assert( var->get_type() );
    172         result = var->get_type();
    173         add_qualifiers( result, CV::Lvalue );
     249        result = shallowCopy( var->get_type() );
     250}
     251
     252bool VariableExpr::get_lvalue() const {
     253        // It isn't always an lvalue, but it is never an rvalue.
     254        return true;
    174255}
    175256
     
    258339: Expr( loc, new BasicType{ BasicType::SignedInt } ), arg1( a1 ), arg2( a2 ), isAnd( ia ) {}
    259340
     341// --- CommaExpr
     342bool CommaExpr::get_lvalue() const {
     343        // This is wrong by C, but the current implementation uses it.
     344        // (ex: Specialize, Lvalue and Box)
     345        return arg2->get_lvalue();
     346}
     347
    260348// --- ConstructorExpr
    261349
     
    276364        assert( t && i );
    277365        result = t;
    278         add_qualifiers( result, CV::Lvalue );
     366}
     367
     368bool CompoundLiteralExpr::get_lvalue() const {
     369        return true;
    279370}
    280371
     
    293384        // like MemberExpr, TupleIndexExpr is always an lvalue
    294385        result = type->types[ index ];
    295         add_qualifiers( result, CV::Lvalue );
     386}
     387
     388bool TupleIndexExpr::get_lvalue() const {
     389        return tuple->get_lvalue();
    296390}
    297391
  • src/AST/Expr.hpp

    r057298e r7030dab  
    3131
    3232// Must be included in *all* AST classes; should be #undef'd at the end of the file
    33 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     33#define MUTATE_FRIEND \
     34    template<typename node_t> friend node_t * mutate(const node_t * node); \
     35        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
     36
    3437
    3538class ConverterOldToNew;
     
    185188
    186189        Expr * set_extension( bool ex ) { extension = ex; return this; }
     190        virtual bool get_lvalue() const;
    187191
    188192        virtual const Expr * accept( Visitor & v ) const override = 0;
     
    201205        ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} );
    202206
     207        bool get_lvalue() const final;
     208
    203209        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    204210private:
     
    215221        UntypedExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} )
    216222        : Expr( loc ), func( f ), args( std::move(as) ) {}
     223
     224        bool get_lvalue() const final;
    217225
    218226        /// Creates a new dereference expression
     
    291299        CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {}
    292300
     301        bool get_lvalue() const final;
     302
    293303        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    294304private:
     
    338348        : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); }
    339349
     350        bool get_lvalue() const final;
     351
    340352        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    341353private:
     
    352364        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg );
    353365
     366        bool get_lvalue() const final;
     367
    354368        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    355369private:
    356370        MemberExpr * clone() const override { return new MemberExpr{ *this }; }
    357371        MUTATE_FRIEND
     372
     373        // Custructor overload meant only for AST conversion
     374        enum NoOpConstruction { NoOpConstructionChosen };
     375        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
     376            NoOpConstruction overloadSelector );
     377        friend class ::ConverterOldToNew;
     378        friend class ::ConverterNewToOld;
    358379};
    359380
     
    365386        VariableExpr( const CodeLocation & loc );
    366387        VariableExpr( const CodeLocation & loc, const DeclWithType * v );
     388
     389        bool get_lvalue() const final;
    367390
    368391        /// generates a function pointer for a given function
     
    532555
    533556        CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
    534         : Expr( loc ), arg1( a1 ), arg2( a2 ) {}
     557        : Expr( loc ), arg1( a1 ), arg2( a2 ) {
     558                this->result = a2->result;
     559        }
     560
     561        bool get_lvalue() const final;
    535562
    536563        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    605632        CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i );
    606633
     634        bool get_lvalue() const final;
     635
    607636        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    608637private:
     
    660689
    661690        TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i );
     691
     692        bool get_lvalue() const final;
    662693
    663694        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Init.hpp

    r057298e r7030dab  
    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

    r057298e r7030dab  
    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

    r057298e r7030dab  
    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

    r057298e r7030dab  
    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 >
     
    202205        container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
    203206
     207        /// Mutate forall-list, accounting for presence of type substitution map
     208        template<typename node_t>
     209        void mutate_forall( const node_t *& );
     210
    204211public:
    205212        /// Logic to call the accept and mutate the parent if needed, delegates call to accept
     
    210217        /// Internal RAII guard for symbol table features
    211218        struct guard_symtab {
    212                 guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass, 0); }
    213                 ~guard_symtab()                                   { __pass::symtab::leave(pass, 0); }
     219                guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass.pass, 0); }
     220                ~guard_symtab()                                   { __pass::symtab::leave(pass.pass, 0); }
    214221                Pass<pass_t> & pass;
    215222        };
     
    217224        /// Internal RAII guard for scope features
    218225        struct guard_scope {
    219                 guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass, 0); }
    220                 ~guard_scope()                                   { __pass::scope::leave(pass, 0); }
     226                guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass.pass, 0); }
     227                ~guard_scope()                                   { __pass::scope::leave(pass.pass, 0); }
    221228                Pass<pass_t> & pass;
     229        };
     230
     231        /// Internal RAII guard for forall substitutions
     232        struct guard_forall_subs {
     233                guard_forall_subs( Pass<pass_t> & pass, const ParameterizedType * type )
     234                : pass( pass ), type( type ) { __pass::forall::enter(pass.pass, 0, type ); }
     235                ~guard_forall_subs()         { __pass::forall::leave(pass.pass, 0, type ); }
     236                Pass<pass_t> & pass;
     237                const ParameterizedType * type;
    222238        };
    223239
     
    314330        SymbolTable symtab;
    315331};
     332
     333/// Use when the templated visitor needs to keep TypeInstType instances properly linked to TypeDecl
     334struct WithForallSubstitutor {
     335        ForallSubstitutionTable subs;
     336};
     337
    316338}
    317339
  • src/AST/Pass.impl.hpp

    r057298e r7030dab  
    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 );
     
    951966        // For now this isn't visited, it is unclear if this causes problem
    952967        // if all tests are known to pass, remove this code
    953         // VISIT(
    954         //      maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
    955         // )
     968        VISIT(
     969                maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
     970        )
    956971
    957972        VISIT_END( Stmt, node );
     
    16791694        VISIT_START( node );
    16801695
    1681         VISIT(
    1682                 maybe_accept( node, &FunctionType::forall  );
     1696        VISIT({
     1697                guard_forall_subs forall_guard { *this, node };
     1698                mutate_forall( node );
    16831699                maybe_accept( node, &FunctionType::returns );
    16841700                maybe_accept( node, &FunctionType::params  );
    1685         )
     1701        })
    16861702
    16871703        VISIT_END( Type, node );
     
    16981714        VISIT({
    16991715                guard_symtab guard { *this };
    1700                 maybe_accept( node, &StructInstType::forall );
     1716                guard_forall_subs forall_guard { *this, node };
     1717                mutate_forall( node );
    17011718                maybe_accept( node, &StructInstType::params );
    17021719        })
     
    17111728        VISIT_START( node );
    17121729
    1713         __pass::symtab::addStruct( pass, 0, node->name );
    1714 
    1715         {
     1730        __pass::symtab::addUnion( pass, 0, node->name );
     1731
     1732        VISIT({
    17161733                guard_symtab guard { *this };
    1717                 maybe_accept( node, &UnionInstType::forall );
     1734                guard_forall_subs forall_guard { *this, node };
     1735                mutate_forall( node );
    17181736                maybe_accept( node, &UnionInstType::params );
    1719         }
     1737        })
    17201738
    17211739        VISIT_END( Type, node );
     
    17281746        VISIT_START( node );
    17291747
    1730         VISIT(
    1731                 maybe_accept( node, &EnumInstType::forall );
     1748        VISIT({
     1749                guard_forall_subs forall_guard { *this, node };
     1750                mutate_forall( node );
    17321751                maybe_accept( node, &EnumInstType::params );
    1733         )
     1752        })
    17341753
    17351754        VISIT_END( Type, node );
     
    17421761        VISIT_START( node );
    17431762
    1744         VISIT(
    1745                 maybe_accept( node, &TraitInstType::forall );
     1763        VISIT({
     1764                guard_forall_subs forall_guard { *this, node };
     1765                mutate_forall( node );
    17461766                maybe_accept( node, &TraitInstType::params );
    1747         )
     1767        })
    17481768
    17491769        VISIT_END( Type, node );
     
    17571777
    17581778        VISIT(
    1759                 maybe_accept( node, &TypeInstType::forall );
    1760                 maybe_accept( node, &TypeInstType::params );
     1779                {
     1780                        guard_forall_subs forall_guard { *this, node };
     1781                        mutate_forall( node );
     1782                        maybe_accept( node, &TypeInstType::params );
     1783                }
     1784                // ensure that base re-bound if doing substitution
     1785                __pass::forall::replace( pass, 0, node );
    17611786        )
    17621787
     
    19071932                                guard_symtab guard { *this };
    19081933                                auto new_node = p.second->accept( *this );
    1909                                 if (new_node != p.second) mutated = false;
     1934                                if (new_node != p.second) mutated = true;
    19101935                                new_map.insert({ p.first, new_node });
    19111936                        }
     
    19231948                                guard_symtab guard { *this };
    19241949                                auto new_node = p.second->accept( *this );
    1925                                 if (new_node != p.second) mutated = false;
     1950                                if (new_node != p.second) mutated = true;
    19261951                                new_map.insert({ p.first, new_node });
    19271952                        }
  • src/AST/Pass.proto.hpp

    r057298e r7030dab  
    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                }
     
    311311                SYMTAB_FUNC1( addUnion  , const UnionDecl *     );
    312312                SYMTAB_FUNC1( addTrait  , const TraitDecl *     );
    313                 SYMTAB_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Node * );
     313                SYMTAB_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Decl * );
    314314
    315315                // A few extra functions have more complicated behaviour, they are hand written
     
    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

    r057298e r7030dab  
    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 {
     
    412414class ImplicitCtorDtorStmt final : public Stmt {
    413415public:
    414         readonly<Stmt> callStmt;
     416        ptr<Stmt> callStmt;
    415417
    416418        ImplicitCtorDtorStmt( const CodeLocation & loc, const Stmt * callStmt,
  • src/AST/Type.cpp

    r057298e r7030dab  
    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
     
    9092// GENERATED END
    9193
     94// --- ParameterizedType
     95
     96void ParameterizedType::initWithSub(
     97        const ParameterizedType & o, Pass< ForallSubstitutor > & sub
     98) {
     99        forall = sub.pass( o.forall );
     100}
     101
    92102// --- FunctionType
     103
     104FunctionType::FunctionType( const FunctionType & o )
     105: ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(),
     106  isVarArgs( o.isVarArgs ) {
     107        Pass< ForallSubstitutor > sub;
     108        initWithSub( o, sub );           // initialize substitution map
     109        returns = sub.pass( o.returns ); // apply to return and parameter types
     110        params = sub.pass( o.params );
     111}
    93112
    94113namespace {
     
    106125
    107126// --- ReferenceToType
     127
     128void ReferenceToType::initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub ) {
     129        ParameterizedType::initWithSub( o, sub ); // initialize substitution
     130        params = sub.pass( o.params );            // apply to parameters
     131}
     132
     133ReferenceToType::ReferenceToType( const ReferenceToType & o )
     134: ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ),
     135  hoistType( o.hoistType ) {
     136        Pass< ForallSubstitutor > sub;
     137        initWithSub( o, sub );
     138}
     139
    108140std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const {
    109141        assertf( aggr(), "Must have aggregate to perform lookup" );
     
    118150// --- StructInstType
    119151
    120 StructInstType::StructInstType( const StructDecl * b, CV::Qualifiers q,
    121         std::vector<ptr<Attribute>>&& as )
    122 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     152StructInstType::StructInstType(
     153        const StructDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
     154: ReferenceToType( b->name, q, move(as) ), base( b ) {}
    123155
    124156bool StructInstType::isComplete() const { return base ? base->body : false; }
     
    126158// --- UnionInstType
    127159
    128 UnionInstType::UnionInstType( const UnionDecl * b, CV::Qualifiers q,
    129         std::vector<ptr<Attribute>>&& as )
    130 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     160UnionInstType::UnionInstType(
     161        const UnionDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
     162: ReferenceToType( b->name, q, move(as) ), base( b ) {}
    131163
    132164bool UnionInstType::isComplete() const { return base ? base->body : false; }
     
    134166// --- EnumInstType
    135167
    136 EnumInstType::EnumInstType( const EnumDecl * b, CV::Qualifiers q,
    137         std::vector<ptr<Attribute>>&& as )
    138 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     168EnumInstType::EnumInstType(
     169        const EnumDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
     170: ReferenceToType( b->name, q, move(as) ), base( b ) {}
    139171
    140172bool EnumInstType::isComplete() const { return base ? base->body : false; }
     
    142174// --- TraitInstType
    143175
    144 TraitInstType::TraitInstType( const TraitDecl * b, CV::Qualifiers q,
    145         std::vector<ptr<Attribute>>&& as )
    146 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     176TraitInstType::TraitInstType(
     177        const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
     178: ReferenceToType( b->name, q, move(as) ), base( b ) {}
    147179
    148180// --- TypeInstType
     181
     182TypeInstType::TypeInstType( const TypeInstType & o )
     183: ReferenceToType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {
     184        Pass< ForallSubstitutor > sub;
     185        initWithSub( o, sub );      // initialize substitution
     186        base = sub.pass( o.base );  // apply to base type
     187}
    149188
    150189void TypeInstType::set_base( const TypeDecl * b ) {
     
    158197
    159198TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q )
    160 : Type( q ), types( std::move(ts) ), members() {
     199: Type( q ), types( move(ts) ), members() {
    161200        // This constructor is awkward. `TupleType` needs to contain objects so that members can be
    162201        // named, but members without initializer nodes end up getting constructors, which breaks
  • src/AST/Type.hpp

    r057298e r7030dab  
    2929
    3030// Must be included in *all* AST classes; should be #undef'd at the end of the file
    31 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     31#define MUTATE_FRIEND \
     32    template<typename node_t> friend node_t * mutate(const node_t * node); \
     33        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3234
    3335namespace ast {
     36
     37template< typename T > class Pass;
     38
     39struct ForallSubstitutor;
    3440
    3541class Type : public Node {
     
    4450        bool is_volatile() const { return qualifiers.is_volatile; }
    4551        bool is_restrict() const { return qualifiers.is_restrict; }
    46         bool is_lvalue() const { return qualifiers.is_lvalue; }
    4752        bool is_mutex() const { return qualifiers.is_mutex; }
    4853        bool is_atomic() const { return qualifiers.is_atomic; }
     
    5156        Type * set_volatile( bool v ) { qualifiers.is_volatile = v; return this; }
    5257        Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; }
    53         Type * set_lvalue( bool v ) { qualifiers.is_lvalue = v; return this; }
    5458        Type * set_mutex( bool v ) { qualifiers.is_mutex = v; return this; }
    5559        Type * set_atomic( bool v ) { qualifiers.is_atomic = v; return this; }
     
    163167        static const char *typeNames[];
    164168
    165         BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 
     169        BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    166170        : Type(q, std::move(as)), kind(k) {}
    167171
     
    265269/// Base type for potentially forall-qualified types
    266270class ParameterizedType : public Type {
     271protected:
     272        /// initializes forall with substitutor
     273        void initWithSub( const ParameterizedType & o, Pass< ForallSubstitutor > & sub );
    267274public:
    268275        using ForallList = std::vector<ptr<TypeDecl>>;
     
    276283        ParameterizedType( CV::Qualifiers q, std::vector<ptr<Attribute>> && as = {} )
    277284        : Type(q, std::move(as)), forall() {}
     285
     286        // enforce use of ForallSubstitutor to copy parameterized type
     287        ParameterizedType( const ParameterizedType & ) = delete;
     288
     289        ParameterizedType( ParameterizedType && ) = default;
     290
     291        // no need to change destructor, and operator= deleted in Node
    278292
    279293private:
     
    301315        : ParameterizedType(q), returns(), params(), isVarArgs(va) {}
    302316
     317        FunctionType( const FunctionType & o );
     318
    303319        /// true if either the parameters or return values contain a tttype
    304320        bool isTtype() const;
     
    314330/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
    315331class ReferenceToType : public ParameterizedType {
     332protected:
     333        /// Initializes forall and parameters based on substitutor
     334        void initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub );
    316335public:
    317336        std::vector<ptr<Expr>> params;
     
    319338        bool hoistType = false;
    320339
    321         ReferenceToType( const std::string& n, CV::Qualifiers q = {},
    322                 std::vector<ptr<Attribute>> && as = {} )
     340        ReferenceToType(
     341                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    323342        : ParameterizedType(q, std::move(as)), params(), name(n) {}
     343
     344        ReferenceToType( const ReferenceToType & o );
    324345
    325346        /// Gets aggregate declaration this type refers to
     
    338359        readonly<StructDecl> base;
    339360
    340         StructInstType( const std::string& n, CV::Qualifiers q = {},
    341                 std::vector<ptr<Attribute>> && as = {} )
     361        StructInstType(
     362                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    342363        : ReferenceToType( n, q, std::move(as) ), base() {}
    343         StructInstType( const StructDecl * b, CV::Qualifiers q = {},
    344                 std::vector<ptr<Attribute>> && as = {} );
     364
     365        StructInstType(
     366                const StructDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    345367
    346368        bool isComplete() const override;
     
    359381        readonly<UnionDecl> base;
    360382
    361         UnionInstType( const std::string& n, CV::Qualifiers q = {},
    362                 std::vector<ptr<Attribute>> && as = {} )
     383        UnionInstType(
     384                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    363385        : ReferenceToType( n, q, std::move(as) ), base() {}
    364         UnionInstType( const UnionDecl * b, CV::Qualifiers q = {},
    365                 std::vector<ptr<Attribute>> && as = {} );
     386
     387        UnionInstType(
     388                const UnionDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    366389
    367390        bool isComplete() const override;
     
    380403        readonly<EnumDecl> base;
    381404
    382         EnumInstType( const std::string& n, CV::Qualifiers q = {},
    383                 std::vector<ptr<Attribute>> && as = {} )
     405        EnumInstType(
     406                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    384407        : ReferenceToType( n, q, std::move(as) ), base() {}
    385         EnumInstType( const EnumDecl * b, CV::Qualifiers q = {},
    386                 std::vector<ptr<Attribute>> && as = {} );
     408
     409        EnumInstType(
     410                const EnumDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    387411
    388412        bool isComplete() const override;
     
    401425        readonly<TraitDecl> base;
    402426
    403         TraitInstType( const std::string& n, CV::Qualifiers q = {},
    404                 std::vector<ptr<Attribute>> && as = {} )
     427        TraitInstType(
     428                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    405429        : ReferenceToType( n, q, std::move(as) ), base() {}
    406         TraitInstType( const TraitDecl * b, CV::Qualifiers q = {},
    407                 std::vector<ptr<Attribute>> && as = {} );
     430
     431        TraitInstType(
     432                const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    408433
    409434        // not meaningful for TraitInstType
     
    424449        TypeDecl::Kind kind;
    425450
    426         TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
     451        TypeInstType(
     452                const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
    427453                std::vector<ptr<Attribute>> && as = {} )
    428454        : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
     
    431457        : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
    432458
     459        TypeInstType( const TypeInstType & o );
     460
    433461        /// sets `base`, updating `kind` correctly
    434462        void set_base( const TypeDecl * );
  • src/AST/TypeEnvironment.hpp

    r057298e r7030dab  
    3737/// Adding this comparison operator significantly improves assertion satisfaction run time for
    3838/// some cases. The current satisfaction algorithm's speed partially depends on the order of
    39 /// assertions. Assertions which have fewer possible matches should appear before assertions 
    40 /// which have more possible matches. This seems to imply that this could be further improved 
    41 /// by providing an indexer as an additional argument and ordering based on the number of 
     39/// assertions. Assertions which have fewer possible matches should appear before assertions
     40/// which have more possible matches. This seems to imply that this could be further improved
     41/// by providing an indexer as an additional argument and ordering based on the number of
    4242/// matches of the same kind (object, function) for the names of the declarations.
    4343///
    44 /// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this 
     44/// I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this
    4545/// comparator.
    4646///
    47 /// Note: since this compares pointers for position, minor changes in the source file that 
    48 /// affect memory layout can alter compilation time in unpredictable ways. For example, the 
    49 /// placement of a line directive can reorder type pointers with respect to each other so that 
    50 /// assertions are seen in different orders, causing a potentially different number of 
    51 /// unification calls when resolving assertions. I've seen a TU go from 36 seconds to 27 
    52 /// seconds by reordering line directives alone, so it would be nice to fix this comparison so 
    53 /// that assertions compare more consistently. I've tried to modify this to compare on mangle 
    54 /// name instead of type as the second comparator, but this causes some assertions to never be 
     47/// Note: since this compares pointers for position, minor changes in the source file that
     48/// affect memory layout can alter compilation time in unpredictable ways. For example, the
     49/// placement of a line directive can reorder type pointers with respect to each other so that
     50/// assertions are seen in different orders, causing a potentially different number of
     51/// unification calls when resolving assertions. I've seen a TU go from 36 seconds to 27
     52/// seconds by reordering line directives alone, so it would be nice to fix this comparison so
     53/// that assertions compare more consistently. I've tried to modify this to compare on mangle
     54/// name instead of type as the second comparator, but this causes some assertions to never be
    5555/// recorded. More investigation is needed.
    5656struct AssertCompare {
     
    8686void print( std::ostream &, const OpenVarSet &, Indenter indent = {} );
    8787
    88 /// Represents an equivalence class of bound type variables, optionally with the concrete type 
     88/// Represents an equivalence class of bound type variables, optionally with the concrete type
    8989/// they bind to.
    9090struct EqvClass {
     
    9595
    9696        EqvClass() : vars(), bound(), allowWidening( true ), data() {}
    97        
     97
    9898        /// Copy-with-bound constructor
    99         EqvClass( const EqvClass & o, const Type * b ) 
     99        EqvClass( const EqvClass & o, const Type * b )
    100100        : vars( o.vars ), bound( b ), allowWidening( o.allowWidening ), data( o.data ) {}
    101101
     
    142142        void writeToSubstitution( TypeSubstitution & sub ) const;
    143143
    144         template< typename node_t, enum Node::ref_type ref_t >
    145         int apply( ptr_base< node_t, ref_t > & type ) const {
     144        template< typename node_t >
     145        auto apply( node_t && type ) const {
    146146                TypeSubstitution sub;
    147147                writeToSubstitution( sub );
    148                 return sub.apply( type );
    149         }
    150 
    151         template< typename node_t, enum Node::ref_type ref_t >
    152         int applyFree( ptr_base< node_t, ref_t > & type ) const {
     148                return sub.apply( std::forward<node_t>(type) );
     149        }
     150
     151        template< typename node_t >
     152        auto applyFree( node_t && type ) const {
    153153                TypeSubstitution sub;
    154154                writeToSubstitution( sub );
    155                 return sub.applyFree( type );
     155                return sub.applyFree( std::forward<node_t>(type) );
    156156        }
    157157
     
    172172        void addActual( const TypeEnvironment & actualEnv, OpenVarSet & openVars );
    173173
    174         /// Binds the type class represented by `typeInst` to the type `bindTo`; will add the class if 
     174        /// Binds the type class represented by `typeInst` to the type `bindTo`; will add the class if
    175175        /// needed. Returns false on failure.
    176         bool bindVar( 
    177                 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 
    178                 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 
     176        bool bindVar(
     177                const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data,
     178                AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars,
    179179                ResolvExpr::WidenMode widen, const SymbolTable & symtab );
    180        
    181         /// Binds the type classes represented by `var1` and `var2` together; will add one or both 
     180
     181        /// Binds the type classes represented by `var1` and `var2` together; will add one or both
    182182        /// classes if needed. Returns false on failure.
    183         bool bindVarToVar( 
    184                 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 
    185                 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 
     183        bool bindVarToVar(
     184                const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data,
     185                AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars,
    186186                ResolvExpr::WidenMode widen, const SymbolTable & symtab );
    187187
     
    198198
    199199        /// Unifies the type bound of `to` with the type bound of `from`, returning false if fails
    200         bool mergeBound( 
     200        bool mergeBound(
    201201                EqvClass & to, const EqvClass & from, OpenVarSet & openVars, const SymbolTable & symtab );
    202202
    203203        /// Merges two type classes from local environment, returning false if fails
    204         bool mergeClasses( 
    205                 ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars, 
     204        bool mergeClasses(
     205                ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars,
    206206                const SymbolTable & symtab );
    207207
  • src/AST/TypeSubstitution.cpp

    r057298e r7030dab  
    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

    r057298e r7030dab  
    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

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

    r057298e r7030dab  
    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

    r057298e r7030dab  
    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) \
     
    589590        AST/DeclReplacer.cpp \
    590591        AST/Expr.cpp \
     592        AST/ForallSubstitutionTable.cpp \
    591593        AST/GenericSubstitution.cpp \
    592594        AST/Init.cpp \
     
    765767        AST/$(DEPDIR)/$(am__dirstamp)
    766768AST/Expr.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
     769AST/ForallSubstitutionTable.$(OBJEXT): AST/$(am__dirstamp) \
     770        AST/$(DEPDIR)/$(am__dirstamp)
    767771AST/GenericSubstitution.$(OBJEXT): AST/$(am__dirstamp) \
    768772        AST/$(DEPDIR)/$(am__dirstamp)
     
    12181222@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/DeclReplacer.Po@am__quote@
    12191223@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Expr.Po@am__quote@
     1224@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/ForallSubstitutionTable.Po@am__quote@
    12201225@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/GenericSubstitution.Po@am__quote@
    12211226@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Init.Po@am__quote@
  • src/ResolvExpr/AdjustExprType.cc

    r057298e r7030dab  
    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

    r057298e r7030dab  
    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

    r057298e r7030dab  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed Jun 5 14:30:00 2019
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Wed Jun 5 14:30:00 2019
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Oct  1 14:55:00 2019
     13// Update Count     : 2
    1414//
    1515
     
    5454                return new ast::CastExpr{ expr, expr->result->stripReferences() };
    5555        }
    56        
     56
    5757        return expr;
    5858}
     
    6161UniqueId globalResnSlot = 0;
    6262
    63 Cost computeConversionCost( 
    64         const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab,
    65         const ast::TypeEnvironment & env
     63Cost computeConversionCost(
     64        const ast::Type * argType, const ast::Type * paramType, bool argIsLvalue,
     65        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
    6666) {
    6767        PRINT(
     
    7474                std::cerr << std::endl;
    7575        )
    76         Cost convCost = conversionCost( argType, paramType, symtab, env );
     76        Cost convCost = conversionCost( argType, paramType, argIsLvalue, symtab, env );
    7777        PRINT(
    7878                std::cerr << std::endl << "cost is " << convCost << std::endl;
     
    107107
    108108        /// Computes conversion cost for a given expression to a given type
    109         const ast::Expr * computeExpressionConversionCost( 
    110                 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 
     109        const ast::Expr * computeExpressionConversionCost(
     110                const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost
    111111        ) {
    112                 Cost convCost = computeConversionCost( arg->result, paramType, symtab, env );
     112                Cost convCost = computeConversionCost(
     113                                arg->result, paramType, arg->get_lvalue(), symtab, env );
    113114                outCost += convCost;
    114115
    115                 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires 
    116                 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 
     116                // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires
     117                // conversion. Ignore poly cost for now, since this requires resolution of the cast to
    117118                // infer parameters and this does not currently work for the reason stated below
    118119                Cost tmpCost = convCost;
     
    123124                        return new ast::CastExpr{ arg, newType };
    124125
    125                         // xxx - *should* be able to resolve this cast, but at the moment pointers are not 
    126                         // castable to zero_t, but are implicitly convertible. This is clearly inconsistent, 
     126                        // xxx - *should* be able to resolve this cast, but at the moment pointers are not
     127                        // castable to zero_t, but are implicitly convertible. This is clearly inconsistent,
    127128                        // once this is fixed it should be possible to resolve the cast.
    128                         // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable, 
    129                         // but it shouldn't be because this makes the conversion from DT* to DT* since 
     129                        // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable,
     130                        // but it shouldn't be because this makes the conversion from DT* to DT* since
    130131                        // commontype(zero_t, DT*) is DT*, rather than nothing
    131132
    132133                        // CandidateFinder finder{ symtab, env };
    133134                        // finder.find( arg, ResolvMode::withAdjustment() );
    134                         // assertf( finder.candidates.size() > 0, 
     135                        // assertf( finder.candidates.size() > 0,
    135136                        //      "Somehow castable expression failed to find alternatives." );
    136                         // assertf( finder.candidates.size() == 1, 
     137                        // assertf( finder.candidates.size() == 1,
    137138                        //      "Somehow got multiple alternatives for known cast expression." );
    138139                        // return finder.candidates.front()->expr;
     
    143144
    144145        /// Computes conversion cost for a given candidate
    145         Cost computeApplicationConversionCost( 
    146                 CandidateRef cand, const ast::SymbolTable & symtab 
     146        Cost computeApplicationConversionCost(
     147                CandidateRef cand, const ast::SymbolTable & symtab
    147148        ) {
    148149                auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >();
     
    167168                                if ( function->isVarArgs ) {
    168169                                        convCost.incUnsafe();
    169                                         PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 
     170                                        PRINT( std::cerr << "end of params with varargs function: inc unsafe: "
    170171                                                << convCost << std::endl; ; )
    171172                                        // convert reference-typed expressions into value-typed expressions
    172                                         cand->expr = ast::mutate_field_index( 
    173                                                 appExpr, &ast::ApplicationExpr::args, i, 
     173                                        cand->expr = ast::mutate_field_index(
     174                                                appExpr, &ast::ApplicationExpr::args, i,
    174175                                                referenceToRvalueConversion( args[i], convCost ) );
    175176                                        continue;
     
    180181                                // Default arguments should be free - don't include conversion cost.
    181182                                // Unwrap them here because they are not relevant to the rest of the system
    182                                 cand->expr = ast::mutate_field_index( 
     183                                cand->expr = ast::mutate_field_index(
    183184                                        appExpr, &ast::ApplicationExpr::args, i, def->expr );
    184185                                ++param;
     
    188189                        // mark conversion cost and also specialization cost of param type
    189190                        const ast::Type * paramType = (*param)->get_type();
    190                         cand->expr = ast::mutate_field_index( 
    191                                 appExpr, &ast::ApplicationExpr::args, i, 
    192                                 computeExpressionConversionCost( 
     191                        cand->expr = ast::mutate_field_index(
     192                                appExpr, &ast::ApplicationExpr::args, i,
     193                                computeExpressionConversionCost(
    193194                                        args[i], paramType, symtab, cand->env, convCost ) );
    194195                        convCost.decSpec( specCost( paramType ) );
     
    198199                if ( param != params.end() ) return Cost::infinity;
    199200
    200                 // specialization cost of return types can't be accounted for directly, it disables 
     201                // specialization cost of return types can't be accounted for directly, it disables
    201202                // otherwise-identical calls, like this example based on auto-newline in the I/O lib:
    202203                //
     
    215216        }
    216217
    217         void makeUnifiableVars( 
    218                 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars, 
    219                 ast::AssertionSet & need 
     218        void makeUnifiableVars(
     219                const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars,
     220                ast::AssertionSet & need
    220221        ) {
    221222                for ( const ast::TypeDecl * tyvar : type->forall ) {
     
    254255
    255256                ArgPack()
    256                 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 
     257                : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ),
    257258                  tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    258                
    259                 ArgPack( 
    260                         const ast::TypeEnvironment & env, const ast::AssertionSet & need, 
     259
     260                ArgPack(
     261                        const ast::TypeEnvironment & env, const ast::AssertionSet & need,
    261262                        const ast::AssertionSet & have, const ast::OpenVarSet & open )
    262                 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 
     263                : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ),
    263264                  open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    264                
     265
    265266                ArgPack(
    266                         std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env, 
    267                         ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open, 
    268                         unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero, 
     267                        std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env,
     268                        ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open,
     269                        unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero,
    269270                        unsigned nextExpl = 0, unsigned explAlt = 0 )
    270271                : parent(parent), expr( expr ), cost( cost ), env( move( env ) ), need( move( need ) ),
    271272                  have( move( have ) ), open( move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ),
    272273                  nextExpl( nextExpl ), explAlt( explAlt ) {}
    273                
     274
    274275                ArgPack(
    275                         const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 
     276                        const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need,
    276277                        ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added )
    277                 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ), 
    278                   need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ), 
     278                : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ),
     279                  need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ),
    279280                  tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {}
    280                
     281
    281282                /// true if this pack is in the middle of an exploded argument
    282283                bool hasExpl() const { return nextExpl > 0; }
     
    286287                        return args[ nextArg-1 ][ explAlt ];
    287288                }
    288                
     289
    289290                /// Ends a tuple expression, consolidating the appropriate args
    290291                void endTuple( const std::vector< ArgPack > & packs ) {
     
    307308
    308309        /// Instantiates an argument to match a parameter, returns false if no matching results left
    309         bool instantiateArgument( 
    310                 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args, 
    311                 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 
    312                 unsigned nTuples = 0 
     310        bool instantiateArgument(
     311                const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args,
     312                std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,
     313                unsigned nTuples = 0
    313314        ) {
    314315                if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) {
     
    318319                                // xxx - dropping initializer changes behaviour from previous, but seems correct
    319320                                // ^^^ need to handle the case where a tuple has a default argument
    320                                 if ( ! instantiateArgument( 
     321                                if ( ! instantiateArgument(
    321322                                        type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;
    322323                                nTuples = 0;
     
    329330                } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) {
    330331                        // paramType is a ttype, consumes all remaining arguments
    331                        
     332
    332333                        // completed tuples; will be spliced to end of results to finish
    333334                        std::vector< ArgPack > finalResults{};
     
    342343                                for ( std::size_t i = genStart; i < genEnd; ++i ) {
    343344                                        unsigned nextArg = results[i].nextArg;
    344                                        
     345
    345346                                        // use next element of exploded tuple if present
    346347                                        if ( results[i].hasExpl() ) {
     
    352353                                                results.emplace_back(
    353354                                                        i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),
    354                                                         copy( results[i].need ), copy( results[i].have ), 
     355                                                        copy( results[i].need ), copy( results[i].have ),
    355356                                                        copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl,
    356357                                                        results[i].explAlt );
     
    370371                                                        // push empty tuple expression
    371372                                                        newResult.parent = i;
    372                                                         std::vector< ast::ptr< ast::Expr > > emptyList;
    373                                                         newResult.expr =
    374                                                                 new ast::TupleExpr{ CodeLocation{}, move( emptyList ) };
     373                                                        newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} };
    375374                                                        argType = newResult.expr->result;
    376375                                                } else {
     
    400399
    401400                                                // check unification for ttype before adding to final
    402                                                 if ( 
    403                                                         unify( 
     401                                                if (
     402                                                        unify(
    404403                                                                ttype, argType, newResult.env, newResult.need, newResult.have,
    405                                                                 newResult.open, symtab ) 
     404                                                                newResult.open, symtab )
    406405                                                ) {
    407406                                                        finalResults.emplace_back( move( newResult ) );
     
    424423                                                if ( expl.exprs.empty() ) {
    425424                                                        results.emplace_back(
    426                                                                 results[i], move( env ), copy( results[i].need ), 
     425                                                                results[i], move( env ), copy( results[i].need ),
    427426                                                                copy( results[i].have ), move( open ), nextArg + 1, expl.cost );
    428                                                        
     427
    429428                                                        continue;
    430429                                                }
     
    432431                                                // add new result
    433432                                                results.emplace_back(
    434                                                         i, expl.exprs.front(), move( env ), copy( results[i].need ), 
    435                                                         copy( results[i].have ), move( open ), nextArg + 1, nTuples, 
     433                                                        i, expl.exprs.front(), move( env ), copy( results[i].need ),
     434                                                        copy( results[i].have ), move( open ), nextArg + 1, nTuples,
    436435                                                        expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    437436                                        }
     
    479478
    480479                                        results.emplace_back(
    481                                                 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 
     480                                                i, expr, move( env ), move( need ), move( have ), move( open ), nextArg,
    482481                                                nTuples, Cost::zero, nextExpl, results[i].explAlt );
    483482                                }
     
    495494                                        if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {
    496495                                                results.emplace_back(
    497                                                         i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 
     496                                                        i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ),
    498497                                                        move( need ), move( have ), move( open ), nextArg, nTuples );
    499498                                        }
     
    517516                                if ( expl.exprs.empty() ) {
    518517                                        results.emplace_back(
    519                                                 results[i], move( env ), move( need ), move( have ), move( open ), 
     518                                                results[i], move( env ), move( need ), move( have ), move( open ),
    520519                                                nextArg + 1, expl.cost );
    521                                        
     520
    522521                                        continue;
    523522                                }
     
    539538                                        // add new result
    540539                                        results.emplace_back(
    541                                                 i, expr, move( env ), move( need ), move( have ), move( open ), 
     540                                                i, expr, move( env ), move( need ), move( have ), move( open ),
    542541                                                nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    543542                                }
     
    548547                genStart = genEnd;
    549548
    550                 return genEnd != results.size();
     549                return genEnd != results.size();  // were any new results added?
    551550        }
    552551
    553552        /// Generate a cast expression from `arg` to `toType`
    554         const ast::Expr * restructureCast( 
     553        const ast::Expr * restructureCast(
    555554                ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast
    556555        ) {
    557                 if ( 
    558                         arg->result->size() > 1 
    559                         && ! toType->isVoid() 
    560                         && ! dynamic_cast< const ast::ReferenceType * >( toType ) 
     556                if (
     557                        arg->result->size() > 1
     558                        && ! toType->isVoid()
     559                        && ! dynamic_cast< const ast::ReferenceType * >( toType )
    561560                ) {
    562                         // Argument is a tuple and the target type is neither void nor a reference. Cast each 
    563                         // member of the tuple to its corresponding target type, producing the tuple of those 
    564                         // cast expressions. If there are more components of the tuple than components in the 
    565                         // target type, then excess components do not come out in the result expression (but 
     561                        // Argument is a tuple and the target type is neither void nor a reference. Cast each
     562                        // member of the tuple to its corresponding target type, producing the tuple of those
     563                        // cast expressions. If there are more components of the tuple than components in the
     564                        // target type, then excess components do not come out in the result expression (but
    566565                        // UniqueExpr ensures that the side effects will still be produced)
    567566                        if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {
    568                                 // expressions which may contain side effects require a single unique instance of 
     567                                // expressions which may contain side effects require a single unique instance of
    569568                                // the expression
    570569                                arg = new ast::UniqueExpr{ arg->location, arg };
     
    574573                                // cast each component
    575574                                ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i };
    576                                 components.emplace_back( 
     575                                components.emplace_back(
    577576                                        restructureCast( idx, toType->getComponent( i ), isGenerated ) );
    578577                        }
     
    594593
    595594        /// Actually visits expressions to find their candidate interpretations
    596         struct Finder final : public ast::WithShortCircuiting {
     595        class Finder final : public ast::WithShortCircuiting {
     596                const ast::SymbolTable & symtab;
     597        public:
    597598                CandidateFinder & selfFinder;
    598                 const ast::SymbolTable & symtab;
    599599                CandidateList & candidates;
    600600                const ast::TypeEnvironment & tenv;
    601601                ast::ptr< ast::Type > & targetType;
    602602
     603                enum Errors {
     604                        NotFound,
     605                        NoMatch,
     606                        ArgsToFew,
     607                        ArgsToMany,
     608                        RetsToFew,
     609                        RetsToMany,
     610                        NoReason
     611                };
     612
     613                struct {
     614                        Errors code = NotFound;
     615                } reason;
     616
    603617                Finder( CandidateFinder & f )
    604                 : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
     618                : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
    605619                  targetType( f.targetType ) {}
    606                
     620
    607621                void previsit( const ast::Node * ) { visit_children = false; }
    608622
     
    611625                void addCandidate( Args &&... args ) {
    612626                        candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } );
     627                        reason.code = NoReason;
    613628                }
    614629
     
    639654
    640655                /// Completes a function candidate with arguments located
    641                 void validateFunctionCandidate( 
    642                         const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 
    643                         CandidateList & out 
     656                void validateFunctionCandidate(
     657                        const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,
     658                        CandidateList & out
    644659                ) {
    645                         ast::ApplicationExpr * appExpr = 
     660                        ast::ApplicationExpr * appExpr =
    646661                                new ast::ApplicationExpr{ func->expr->location, func->expr };
    647662                        // sum cost and accumulate arguments
     
    657672                        appExpr->args = move( vargs );
    658673                        // build and validate new candidate
    659                         auto newCand = 
     674                        auto newCand =
    660675                                std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );
    661676                        PRINT(
     
    669684                /// Builds a list of candidates for a function, storing them in out
    670685                void makeFunctionCandidates(
    671                         const CandidateRef & func, const ast::FunctionType * funcType, 
     686                        const CandidateRef & func, const ast::FunctionType * funcType,
    672687                        const ExplodedArgs_new & args, CandidateList & out
    673688                ) {
     
    676691                        ast::TypeEnvironment funcEnv{ func->env };
    677692                        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
     693                        // add all type variables as open variables now so that those not used in the
     694                        // parameter list are still considered open
    680695                        funcEnv.add( funcType->forall );
    681696
     
    683698                                // attempt to narrow based on expected target type
    684699                                const ast::Type * returnType = funcType->returns.front()->get_type();
    685                                 if ( ! unify( 
    686                                         returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 
     700                                if ( ! unify(
     701                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
    687702                                ) {
    688703                                        // unification failed, do not pursue this candidate
     
    698713                        for ( const ast::DeclWithType * param : funcType->params ) {
    699714                                auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
    700                                 // Try adding the arguments corresponding to the current parameter to the existing 
     715                                // Try adding the arguments corresponding to the current parameter to the existing
    701716                                // matches
    702                                 if ( ! instantiateArgument( 
     717                                if ( ! instantiateArgument(
    703718                                        obj->type, obj->init, args, results, genStart, symtab ) ) return;
    704719                        }
     
    750765                                                        if ( expl.exprs.empty() ) {
    751766                                                                results.emplace_back(
    752                                                                         results[i], move( env ), copy( results[i].need ), 
    753                                                                         copy( results[i].have ), move( open ), nextArg + 1, 
     767                                                                        results[i], move( env ), copy( results[i].need ),
     768                                                                        copy( results[i].have ), move( open ), nextArg + 1,
    754769                                                                        expl.cost );
    755770
     
    760775                                                        results.emplace_back(
    761776                                                                i, expl.exprs.front(), move( env ), copy( results[i].need ),
    762                                                                 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 
     777                                                                copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost,
    763778                                                                expl.exprs.size() == 1 ? 0 : 1, j );
    764779                                                }
     
    780795                /// Adds implicit struct-conversions to the alternative list
    781796                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 
     797                        // adds anonymous member interpretations whenever an aggregate value type is seen.
     798                        // it's okay for the aggregate expression to have reference type -- cast it to the
    784799                        // base type to treat the aggregate as the referenced value
    785800                        ast::ptr< ast::Expr > aggrExpr( cand->expr );
    786801                        ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;
    787802                        cand->env.apply( aggrType );
    788                        
     803
    789804                        if ( aggrType.as< ast::ReferenceType >() ) {
    790805                                aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };
     
    799814
    800815                /// 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 
     816                void addAggMembers(
     817                        const ast::ReferenceToType * aggrInst, const ast::Expr * expr,
     818                        const Candidate & cand, const Cost & addedCost, const std::string & name
    804819                ) {
    805820                        for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {
    806821                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );
    807                                 CandidateRef newCand = std::make_shared<Candidate>( 
     822                                CandidateRef newCand = std::make_shared<Candidate>(
    808823                                        cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
    809                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     824                                // add anonymous member interpretations whenever an aggregate value type is seen
    810825                                // as a member expression
    811826                                addAnonConversions( newCand );
     
    815830
    816831                /// 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 
     832                void addTupleMembers(
     833                        const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,
     834                        const Cost & addedCost, const ast::Expr * member
    820835                ) {
    821836                        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 
     837                                // get the value of the constant expression as an int, must be between 0 and the
    823838                                // length of the tuple to have meaning
    824839                                long long val = constantExpr->intValue();
    825840                                if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    826841                                        addCandidate(
    827                                                 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 
     842                                                cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },
    828843                                                addedCost );
    829844                                }
     
    837852                        if ( funcFinder.candidates.empty() ) return;
    838853
    839                         std::vector< CandidateFinder > argCandidates =
     854                        reason.code = NoMatch;
     855
     856                        std::vector< CandidateFinder > argCandidates =
    840857                                selfFinder.findSubExprs( untypedExpr->args );
    841                        
     858
    842859                        // take care of possible tuple assignments
    843860                        // if not tuple assignment, handled as normal function call
     
    877894                                                if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    878895                                                        CandidateRef newFunc{ new Candidate{ *func } };
    879                                                         newFunc->expr = 
     896                                                        newFunc->expr =
    880897                                                                referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    881898                                                        makeFunctionCandidates( newFunc, function, argExpansions, found );
    882899                                                }
    883                                         } else if ( 
    884                                                 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 
     900                                        } else if (
     901                                                auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
    885902                                        ) {
    886903                                                if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) {
    887904                                                        if ( auto function = clz->bound.as< ast::FunctionType >() ) {
    888905                                                                CandidateRef newFunc{ new Candidate{ *func } };
    889                                                                 newFunc->expr = 
     906                                                                newFunc->expr =
    890907                                                                        referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    891908                                                                makeFunctionCandidates( newFunc, function, argExpansions, found );
     
    901918                                std::vector< ExplodedArg > funcE;
    902919                                funcE.reserve( funcFinder.candidates.size() );
    903                                 for ( const CandidateRef & func : funcFinder ) { 
     920                                for ( const CandidateRef & func : funcFinder ) {
    904921                                        funcE.emplace_back( *func, symtab );
    905922                                }
     
    913930                                                        if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    914931                                                                CandidateRef newOp{ new Candidate{ *op} };
    915                                                                 newOp->expr = 
     932                                                                newOp->expr =
    916933                                                                        referenceToRvalueConversion( newOp->expr, newOp->cost );
    917934                                                                makeFunctionCandidates( newOp, function, argExpansions, found );
     
    922939                        }
    923940
    924                         // Implement SFINAE; resolution errors are only errors if there aren't any non-error 
     941                        // Implement SFINAE; resolution errors are only errors if there aren't any non-error
    925942                        // candidates
    926943                        if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
     
    934951                                        auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
    935952                                        auto function = pointer->base.strict_as< ast::FunctionType >();
    936                                        
     953
    937954                                        std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;
    938955                                        std::cerr << "parameters are:" << std::endl;
     
    957974                        promoteCvtCost( winners );
    958975
    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 
     976                        // function may return a struct/union value, in which case we need to add candidates
     977                        // for implicit conversions to each of the anonymous members, which must happen after
    961978                        // `findMinCost`, since anon conversions are never the cheapest
    962979                        for ( const CandidateRef & c : winners ) {
     
    966983
    967984                        if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
    968                                 // If resolution is unsuccessful with a target type, try again without, since it 
     985                                // If resolution is unsuccessful with a target type, try again without, since it
    969986                                // will sometimes succeed when it wouldn't with a target type binding.
    970987                                // For example:
     
    9831000                /// true if expression is an lvalue
    9841001                static bool isLvalue( const ast::Expr * x ) {
    985                         return x->result && ( x->result->is_lvalue() || x->result.as< ast::ReferenceType >() );
     1002                        return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() );
    9861003                }
    9871004
     
    9891006                        CandidateFinder finder{ symtab, tenv };
    9901007                        finder.find( addressExpr->arg );
     1008
     1009                        if( finder.candidates.empty() ) return;
     1010
     1011                        reason.code = NoMatch;
     1012
    9911013                        for ( CandidateRef & r : finder.candidates ) {
    9921014                                if ( ! isLvalue( r->expr ) ) continue;
     
    10091031                        finder.find( castExpr->arg, ResolvMode::withAdjustment() );
    10101032
     1033                        if( !finder.candidates.empty() ) reason.code = NoMatch;
     1034
    10111035                        CandidateList matches;
    10121036                        for ( CandidateRef & cand : finder.candidates ) {
     
    10161040                                cand->env.extractOpenVars( open );
    10171041
    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 
     1042                                // It is possible that a cast can throw away some values in a multiply-valued
     1043                                // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the
     1044                                // subexpression results that are cast directly. The candidate is invalid if it
    10211045                                // has fewer results than there are types to cast to.
    10221046                                int discardedValues = cand->expr->result->size() - toType->size();
     
    10251049                                // unification run for side-effects
    10261050                                unify( toType, cand->expr->result, cand->env, need, have, open, symtab );
    1027                                 Cost thisCost = castCost( cand->expr->result, toType, symtab, cand->env );
     1051                                Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1052                                                symtab, cand->env );
    10281053                                PRINT(
    10291054                                        std::cerr << "working on cast with result: " << toType << std::endl;
     
    10371062                                        // count one safe conversion for each value that is thrown away
    10381063                                        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, 
     1064                                        CandidateRef newCand = std::make_shared<Candidate>(
     1065                                                restructureCast( cand->expr, toType, castExpr->isGenerated ),
     1066                                                copy( cand->env ), move( open ), move( need ), cand->cost,
    10421067                                                cand->cost + thisCost );
    10431068                                        inferParameters( newCand, matches );
     
    10571082                        finder.find( castExpr->arg, ResolvMode::withoutPrune() );
    10581083                        for ( CandidateRef & r : finder.candidates ) {
    1059                                 addCandidate( 
    1060                                         *r, 
     1084                                addCandidate(
     1085                                        *r,
    10611086                                        new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
    10621087                        }
     
    10671092                        aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    10681093                        for ( CandidateRef & agg : aggFinder.candidates ) {
    1069                                 // it's okay for the aggregate expression to have reference type -- cast it to the 
     1094                                // it's okay for the aggregate expression to have reference type -- cast it to the
    10701095                                // base type to treat the aggregate as the referenced value
    10711096                                Cost addedCost = Cost::zero;
     
    10741099                                // find member of the given type
    10751100                                if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {
    1076                                         addAggMembers( 
     1101                                        addAggMembers(
    10771102                                                structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10781103                                } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {
    1079                                         addAggMembers( 
     1104                                        addAggMembers(
    10801105                                                unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10811106                                } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {
     
    10921117                        std::vector< ast::SymbolTable::IdData > declList = symtab.lookupId( nameExpr->name );
    10931118                        PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
     1119                        if( declList.empty() ) return;
     1120
     1121                        reason.code = NoMatch;
     1122
    10941123                        for ( auto & data : declList ) {
    10951124                                Cost cost = Cost::zero;
     
    10971126
    10981127                                CandidateRef newCand = std::make_shared<Candidate>(
    1099                                         newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 
     1128                                        newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
    11001129                                        cost );
    11011130                                PRINT(
     
    11071136                                        std::cerr << std::endl;
    11081137                                )
    1109                                 newCand->expr = ast::mutate_field( 
    1110                                         newCand->expr.get(), &ast::Expr::result, 
     1138                                newCand->expr = ast::mutate_field(
     1139                                        newCand->expr.get(), &ast::Expr::result,
    11111140                                        renameTyVars( newCand->expr->result ) );
    1112                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     1141                                // add anonymous member interpretations whenever an aggregate value type is seen
    11131142                                // as a name expression
    11141143                                addAnonConversions( newCand );
     
    11201149                        // not sufficient to just pass `variableExpr` here, type might have changed since
    11211150                        // creation
    1122                         addCandidate( 
     1151                        addCandidate(
    11231152                                new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
    11241153                }
     
    11301159                void postvisit( const ast::SizeofExpr * sizeofExpr ) {
    11311160                        if ( sizeofExpr->type ) {
    1132                                 addCandidate( 
    1133                                         new ast::SizeofExpr{ 
    1134                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 
     1161                                addCandidate(
     1162                                        new ast::SizeofExpr{
     1163                                                sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
    11351164                                        tenv );
    11361165                        } else {
     
    11411170                                CandidateList winners = findMinCost( finder.candidates );
    11421171                                if ( winners.size() != 1 ) {
    1143                                         SemanticError( 
     1172                                        SemanticError(
    11441173                                                sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );
    11451174                                }
     
    11541183                void postvisit( const ast::AlignofExpr * alignofExpr ) {
    11551184                        if ( alignofExpr->type ) {
    1156                                 addCandidate( 
    1157                                         new ast::AlignofExpr{ 
    1158                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 
     1185                                addCandidate(
     1186                                        new ast::AlignofExpr{
     1187                                                alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
    11591188                                        tenv );
    11601189                        } else {
     
    11651194                                CandidateList winners = findMinCost( finder.candidates );
    11661195                                if ( winners.size() != 1 ) {
    1167                                         SemanticError( 
     1196                                        SemanticError(
    11681197                                                alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );
    11691198                                }
     
    11721201                                choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    11731202                                choice->cost = Cost::zero;
    1174                                 addCandidate( 
     1203                                addCandidate(
    11751204                                        *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );
    11761205                        }
     
    11851214                        for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {
    11861215                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );
    1187                                 addCandidate( 
     1216                                addCandidate(
    11881217                                        new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );
    11891218                        }
     
    12061235                        finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );
    12071236                        if ( finder2.candidates.empty() ) return;
     1237
     1238                        reason.code = NoMatch;
    12081239
    12091240                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    12181249
    12191250                                        addCandidate(
    1220                                                 new ast::LogicalExpr{ 
     1251                                                new ast::LogicalExpr{
    12211252                                                        logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
    12221253                                                move( env ), move( open ), move( need ), r1->cost + r2->cost );
     
    12401271                        finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );
    12411272                        if ( finder3.candidates.empty() ) return;
     1273
     1274                        reason.code = NoMatch;
    12421275
    12431276                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    12561289                                                ast::AssertionSet have;
    12571290
    1258                                                 // unify true and false results, then infer parameters to produce new 
     1291                                                // unify true and false results, then infer parameters to produce new
    12591292                                                // candidates
    12601293                                                ast::ptr< ast::Type > common;
    1261                                                 if ( 
    1262                                                         unify( 
    1263                                                                 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 
    1264                                                                 common ) 
     1294                                                if (
     1295                                                        unify(
     1296                                                                r2->expr->result, r3->expr->result, env, need, have, open, symtab,
     1297                                                                common )
    12651298                                                ) {
    12661299                                                        // generate typed expression
    1267                                                         ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 
     1300                                                        ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{
    12681301                                                                conditionalExpr->location, r1->expr, r2->expr, r3->expr };
    12691302                                                        newExpr->result = common ? common : r2->expr->result;
    12701303                                                        // convert both options to result type
    12711304                                                        Cost cost = r1->cost + r2->cost + r3->cost;
    1272                                                         newExpr->arg2 = computeExpressionConversionCost( 
     1305                                                        newExpr->arg2 = computeExpressionConversionCost(
    12731306                                                                newExpr->arg2, newExpr->result, symtab, env, cost );
    12741307                                                        newExpr->arg3 = computeExpressionConversionCost(
     
    12871320                        ast::TypeEnvironment env{ tenv };
    12881321                        ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
    1289                        
     1322
    12901323                        CandidateFinder finder2{ symtab, env };
    12911324                        finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
     
    13171350                        finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );
    13181351                        if ( finder2.candidates.empty() ) return;
     1352
     1353                        reason.code = NoMatch;
    13191354
    13201355                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    13301365
    13311366                                        ast::ptr< ast::Type > common;
    1332                                         if ( 
    1333                                                 unify( 
    1334                                                         r1->expr->result, r2->expr->result, env, need, have, open, symtab, 
    1335                                                         common ) 
     1367                                        if (
     1368                                                unify(
     1369                                                        r1->expr->result, r2->expr->result, env, need, have, open, symtab,
     1370                                                        common )
    13361371                                        ) {
    13371372                                                // generate new expression
    1338                                                 ast::RangeExpr * newExpr = 
     1373                                                ast::RangeExpr * newExpr =
    13391374                                                        new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
    13401375                                                newExpr->result = common ? common : r1->expr->result;
    13411376                                                // add candidate
    13421377                                                CandidateRef newCand = std::make_shared<Candidate>(
    1343                                                         newExpr, move( env ), move( open ), move( need ), 
     1378                                                        newExpr, move( env ), move( open ), move( need ),
    13441379                                                        r1->cost + r2->cost );
    13451380                                                inferParameters( newCand, candidates );
     
    13501385
    13511386                void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
    1352                         std::vector< CandidateFinder > subCandidates = 
     1387                        std::vector< CandidateFinder > subCandidates =
    13531388                                selfFinder.findSubExprs( tupleExpr->exprs );
    13541389                        std::vector< CandidateList > possibilities;
     
    13701405
    13711406                                addCandidate(
    1372                                         new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 
     1407                                        new ast::TupleExpr{ tupleExpr->location, move( exprs ) },
    13731408                                        move( env ), move( open ), move( need ), sumCost( subs ) );
    13741409                        }
     
    14121447                                toType = SymTab::validateType( initExpr->location, toType, symtab );
    14131448                                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. 
     1449                                // The call to find must occur inside this loop, otherwise polymorphic return
     1450                                // types are not bound to the initialization type, since return type variables are
     1451                                // only open for the duration of resolving the UntypedExpr.
    14171452                                CandidateFinder finder{ symtab, tenv, toType };
    14181453                                finder.find( initExpr->expr, ResolvMode::withAdjustment() );
    14191454                                for ( CandidateRef & cand : finder.candidates ) {
     1455                                        if(reason.code == NotFound) reason.code = NoMatch;
     1456
    14201457                                        ast::TypeEnvironment env{ cand->env };
    14211458                                        ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;
     
    14261463                                        )
    14271464
    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 
     1465                                        // It is possible that a cast can throw away some values in a multiply-valued
     1466                                        // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of
     1467                                        // the subexpression results that are cast directly. The candidate is invalid
    14311468                                        // if it has fewer results than there are types to cast to.
    14321469                                        int discardedValues = cand->expr->result->size() - toType->size();
     
    14351472                                        // unification run for side-effects
    14361473                                        unify( toType, cand->expr->result, env, need, have, open, symtab );
    1437                                         Cost thisCost = castCost( cand->expr->result, toType, symtab, env );
    1438                                        
     1474                                        Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1475                                                        symtab, env );
     1476
    14391477                                        if ( thisCost != Cost::infinity ) {
    14401478                                                // count one safe conversion for each value that is thrown away
    14411479                                                thisCost.incSafe( discardedValues );
    1442                                                 CandidateRef newCand = std::make_shared<Candidate>( 
    1443                                                         new ast::InitExpr{ 
    1444                                                                 initExpr->location, restructureCast( cand->expr, toType ), 
    1445                                                                 initAlt.designation }, 
     1480                                                CandidateRef newCand = std::make_shared<Candidate>(
     1481                                                        new ast::InitExpr{
     1482                                                                initExpr->location, restructureCast( cand->expr, toType ),
     1483                                                                initAlt.designation },
    14461484                                                        copy( cand->env ), move( open ), move( need ), cand->cost, thisCost );
    14471485                                                inferParameters( newCand, matches );
     
    14691507        };
    14701508
    1471         /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 
     1509        /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
    14721510        /// return type. Skips ambiguous candidates.
    14731511        CandidateList pruneCandidates( CandidateList & candidates ) {
     
    14861524                        {
    14871525                                ast::ptr< ast::Type > newType = candidate->expr->result;
     1526                                assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());
    14881527                                candidate->env.apply( newType );
    14891528                                mangleName = Mangle::mangle( newType );
     
    14941533                                if ( candidate->cost < found->second.candidate->cost ) {
    14951534                                        PRINT(
    1496                                                 std::cerr << "cost " << candidate->cost << " beats " 
     1535                                                std::cerr << "cost " << candidate->cost << " beats "
    14971536                                                        << found->second.candidate->cost << std::endl;
    14981537                                        )
     
    15001539                                        found->second = PruneStruct{ candidate };
    15011540                                } 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 
     1541                                        // if one of the candidates contains a deleted identifier, can pick the other,
     1542                                        // since deleted expressions should not be ambiguous if there is another option
    15041543                                        // that is at least as good
    15051544                                        if ( findDeletedExpr( candidate->expr ) ) {
     
    15151554                                } else {
    15161555                                        PRINT(
    1517                                                 std::cerr << "cost " << candidate->cost << " loses to " 
     1556                                                std::cerr << "cost " << candidate->cost << " loses to "
    15181557                                                        << found->second.candidate->cost << std::endl;
    15191558                                        )
     
    15301569
    15311570                        CandidateRef cand = target.second.candidate;
    1532                        
     1571
    15331572                        ast::ptr< ast::Type > newResult = cand->expr->result;
    15341573                        cand->env.applyFree( newResult );
    15351574                        cand->expr = ast::mutate_field(
    15361575                                cand->expr.get(), &ast::Expr::result, move( newResult ) );
    1537                        
     1576
    15381577                        out.emplace_back( cand );
    15391578                }
     
    15491588
    15501589        if ( mode.failFast && candidates.empty() ) {
    1551                 SemanticError( expr, "No reasonable alternatives for expression " );
     1590                switch(finder.pass.reason.code) {
     1591                case Finder::NotFound:
     1592                        { SemanticError( expr, "No alternatives for expression " ); break; }
     1593                case Finder::NoMatch:
     1594                        { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; }
     1595                case Finder::ArgsToFew:
     1596                case Finder::ArgsToMany:
     1597                case Finder::RetsToFew:
     1598                case Finder::RetsToMany:
     1599                case Finder::NoReason:
     1600                default:
     1601                        { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); }
     1602                }
    15521603        }
    15531604
     
    15581609                std::vector< std::string > errors;
    15591610                for ( CandidateRef & candidate : candidates ) {
    1560                         satisfyAssertions( candidate, symtab, satisfied, errors );
     1611                        satisfyAssertions( candidate, localSyms, satisfied, errors );
    15611612                }
    15621613
     
    15831634
    15841635                CandidateList pruned = pruneCandidates( candidates );
    1585                
     1636
    15861637                if ( mode.failFast && pruned.empty() ) {
    15871638                        std::ostringstream stream;
     
    16021653                )
    16031654                PRINT(
    1604                         std::cerr << "there are " << candidates.size() << " alternatives after elimination" 
     1655                        std::cerr << "there are " << candidates.size() << " alternatives after elimination"
    16051656                                << std::endl;
    16061657                )
    16071658        }
    16081659
    1609         // adjust types after pruning so that types substituted by pruneAlternatives are correctly 
     1660        // adjust types after pruning so that types substituted by pruneAlternatives are correctly
    16101661        // adjusted
    16111662        if ( mode.adjust ) {
    16121663                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 ) );
     1664                        r->expr = ast::mutate_field(
     1665                                r->expr.get(), &ast::Expr::result,
     1666                                adjustExprType( r->expr->result, r->env, localSyms ) );
    16161667                }
    16171668        }
     
    16251676}
    16261677
    1627 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 
    1628         const std::vector< ast::ptr< ast::Expr > > & xs 
     1678std::vector< CandidateFinder > CandidateFinder::findSubExprs(
     1679        const std::vector< ast::ptr< ast::Expr > > & xs
    16291680) {
    16301681        std::vector< CandidateFinder > out;
    16311682
    16321683        for ( const auto & x : xs ) {
    1633                 out.emplace_back( symtab, env );
     1684                out.emplace_back( localSyms, env );
    16341685                out.back().find( x, ResolvMode::withAdjustment() );
    1635                
     1686
    16361687                PRINT(
    16371688                        std::cerr << "findSubExprs" << std::endl;
  • src/ResolvExpr/CandidateFinder.hpp

    r057298e r7030dab  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed Jun 5 14:30:00 2019
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Wed Jun 5 14:30:00 2019
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Oct  1  9:51:00 2019
     13// Update Count     : 2
    1414//
    1515
     
    2828struct CandidateFinder {
    2929        CandidateList candidates;          ///< List of candidate resolutions
    30         const ast::SymbolTable & symtab;   ///< Symbol table to lookup candidates
     30        const ast::SymbolTable & localSyms;   ///< Symbol table to lookup candidates
    3131        const ast::TypeEnvironment & env;  ///< Substitutions performed in this resolution
    3232        ast::ptr< ast::Type > targetType;  ///< Target type for resolution
    3333
    34         CandidateFinder( 
    35                 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
     34        CandidateFinder(
     35                const ast::SymbolTable & syms, const ast::TypeEnvironment & env,
    3636                const ast::Type * tt = nullptr )
    37         : candidates(), symtab( symtab ), env( env ), targetType( tt ) {}
     37        : candidates(), localSyms( syms ), env( env ), targetType( tt ) {}
    3838
    3939        /// Fill candidates with feasible resolutions for `expr`
     
    4949        iterator begin() { return candidates.begin(); }
    5050        const_iterator begin() const { return candidates.begin(); }
    51        
     51
    5252        iterator end() { return candidates.end(); }
    5353        const_iterator end() const { return candidates.end(); }
     
    5555
    5656/// Computes conversion cost between two types
    57 Cost computeConversionCost( 
    58         const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab,
    59         const ast::TypeEnvironment & env );
     57Cost computeConversionCost(
     58        const ast::Type * argType, const ast::Type * paramType, bool argIsLvalue,
     59        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
    6060
    6161} // namespace ResolvExpr
  • src/ResolvExpr/CastCost.cc

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

    r057298e r7030dab  
    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

    r057298e r7030dab  
    1010// Created On       : Sun May 17 07:06:19 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Aug 12 10:21:00 2019
    13 // Update Count     : 27
     12// Last Modified On : Fri Oct  4 14:45:00 2019
     13// Update Count     : 28
    1414//
    1515
     
    497497        }
    498498
    499 static int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
    500                 const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
    501         return ptrsAssignable( t1, t2, env );
    502 }
    503 
    504 // TODO: This is used for overload resolution. It might be able to be dropped once the old system
    505 // is removed.
    506 static Cost localConversionCost(
    507         const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    508         const ast::TypeEnvironment & env
    509 ) { return conversionCost( src, dst, symtab, env ); }
     499namespace {
     500        # warning For overload resolution between the two versions.
     501        int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
     502                        const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
     503                return ptrsAssignable( t1, t2, env );
     504        }
     505        Cost localConversionCost(
     506                const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
     507                const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
     508        ) { return conversionCost( src, dst, srcIsLvalue, symtab, env ); }
     509}
    510510
    511511Cost conversionCost(
    512         const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    513         const ast::TypeEnvironment & env
     512        const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
     513        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
    514514) {
    515515        if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    516516                if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) {
    517517                        if ( eqv->bound ) {
    518                                 return conversionCost(src, eqv->bound, symtab, env );
     518                                return conversionCost(src, eqv->bound, srcIsLvalue, symtab, env );
    519519                        } else {
    520520                                return Cost::infinity;
     
    524524                        assertf( type, "Unexpected typedef." );
    525525                        if ( type->base ) {
    526                                 return conversionCost( src, type->base, symtab, env ) + Cost::safe;
     526                                return conversionCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe;
    527527                        }
    528528                }
     
    534534        } else if ( const ast::ReferenceType * refType =
    535535                         dynamic_cast< const ast::ReferenceType * >( dst ) ) {
    536                 return convertToReferenceCost( src, refType, symtab, env, localPtrsAssignable );
     536                return convertToReferenceCost( src, refType, srcIsLvalue, symtab, env, localPtrsAssignable );
    537537        } else {
    538                 ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
     538                ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
    539539                src->accept( converter );
    540540                return converter.pass.cost;
     
    542542}
    543543
    544 static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst,
     544static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
    545545                int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
    546                 NumCostCalculation func ) {
     546                PtrsCalculation func ) {
    547547        if ( 0 < diff ) {
    548548                Cost cost = convertToReferenceCost(
    549                         strict_dynamic_cast< const ast::ReferenceType * >( src )->base,
    550                         dst, (diff - 1), symtab, env, func );
     549                        strict_dynamic_cast< const ast::ReferenceType * >( src )->base, dst,
     550                        srcIsLvalue, (diff - 1), symtab, env, func );
    551551                cost.incReference();
    552552                return cost;
     
    554554                Cost cost = convertToReferenceCost(
    555555                        src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base,
    556                         (diff + 1), symtab, env, func );
     556                        srcIsLvalue, (diff + 1), symtab, env, func );
    557557                cost.incReference();
    558558                return cost;
     
    579579                        }
    580580                } else {
    581                         ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
     581                        ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
    582582                        src->accept( converter );
    583583                        return converter.pass.cost;
     
    588588                assert( dstAsRef );
    589589                if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
    590                         if ( src->is_lvalue() ) {
     590                        if ( srcIsLvalue ) {
    591591                                if ( src->qualifiers == dstAsRef->base->qualifiers ) {
    592592                                        return Cost::reference;
     
    607607
    608608Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst,
    609             const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
    610                 NumCostCalculation func ) {
     609                bool srcIsLvalue, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
     610                PtrsCalculation func ) {
    611611        int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth();
    612         return convertToReferenceCost( src, dst, sdepth - ddepth, symtab, env, func );
     612        return convertToReferenceCost( src, dst, srcIsLvalue, sdepth - ddepth, symtab, env, func );
    613613}
    614614
     
    667667        assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
    668668
    669         cost = costCalc( refType->base, dst, symtab, env );
     669        cost = costCalc( refType->base, dst, srcIsLvalue, symtab, env );
    670670        if ( refType->base->qualifiers == dst->qualifiers ) {
    671671                cost.incReference();
     
    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, srcIsLvalue, symtab, env );
    705705        if ( cost < Cost::unsafe ) {
    706706                cost.incSafe();
     
    714714void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) {
    715715        if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) {
    716                 cost = costCalc( eqv->bound, dst, symtab, env );
     716                cost = costCalc( eqv->bound, dst, srcIsLvalue, symtab, env );
    717717        } else if ( const ast::TypeInstType * dstAsInst =
    718718                        dynamic_cast< const ast::TypeInstType * >( dst ) ) {
     
    724724                assertf( type, "Unexpected typedef.");
    725725                if ( type->base ) {
    726                         cost = costCalc( type->base, dst, symtab, env ) + Cost::safe;
     726                        cost = costCalc( type->base, dst, srcIsLvalue, symtab, env ) + Cost::safe;
    727727                }
    728728        }
     
    737737                auto dstEnd = dstAsTuple->types.end();
    738738                while ( srcIt != srcEnd && dstIt != dstEnd ) {
    739                         Cost newCost = costCalc( * srcIt++, * dstIt++, symtab, env );
     739                        Cost newCost = costCalc( * srcIt++, * dstIt++, srcIsLvalue, symtab, env );
    740740                        if ( newCost == Cost::infinity ) {
    741741                                return;
     
    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/ConversionCost.h

    r057298e r7030dab  
    1010// Created On       : Sun May 17 09:37:28 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Aug  8 16:13:00 2019
    13 // Update Count     : 6
     12// Last Modified On : Tue Oct  4 14:59:00 2019
     13// Update Count     : 7
    1414//
    1515
     
    7474
    7575// Some function pointer types, differ in return type.
    76 using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *,
     76using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *, bool,
    7777        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
    78 using NumCostCalculation = std::function<int(const ast::Type *, const ast::Type *,
     78using PtrsCalculation = std::function<int(const ast::Type *, const ast::Type *,
    7979        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
    8080
     
    8383protected:
    8484        const ast::Type * dst;
     85        bool srcIsLvalue;
    8586        const ast::SymbolTable & symtab;
    8687        const ast::TypeEnvironment & env;
     
    8990        Cost cost;
    9091
    91         ConversionCost_new( const ast::Type * dst, const ast::SymbolTable & symtab,
     92        ConversionCost_new( const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab,
    9293                        const ast::TypeEnvironment & env, CostCalculation costCalc ) :
    93                 dst( dst ), symtab( symtab ), env( env ), costCalc( costCalc ), cost( Cost::infinity )
     94                dst( dst ), srcIsLvalue( srcIsLvalue ), symtab( symtab ), env( env ),
     95                costCalc( costCalc ), cost( Cost::infinity )
    9496        {}
    9597
     
    114116
    115117Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,
    116         const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, NumCostCalculation func );
     118        bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env,
     119        PtrsCalculation func );
    117120
    118121} // namespace ResolvExpr
  • src/ResolvExpr/CurrentObject.cc

    r057298e r7030dab  
    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

    r057298e r7030dab  
    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

    r057298e r7030dab  
    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

    r057298e r7030dab  
    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

    r057298e r7030dab  
    10741074                        const ast::Expr * postmutate( const ast::CastExpr * castExpr ) {
    10751075                                if (
    1076                                         castExpr->isGenerated
     1076                                        castExpr->isGenerated == ast::GeneratedCast
    10771077                                        && typesCompatible( castExpr->arg->result, castExpr->result )
    10781078                                ) {
     
    11281128
    11291129                // set up and resolve expression cast to void
    1130                 ast::CastExpr * untyped = new ast::CastExpr{ expr };
     1130                ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
    11311131                CandidateRef choice = findUnfinishedKindExpression(
    11321132                        untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
     
    12671267        };
    12681268
    1269         void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) {
     1269        void resolve( std::list< ast::ptr< ast::Decl > >& translationUnit ) {
    12701270                ast::Pass< Resolver_new > resolver;
    12711271                accept_all( translationUnit, resolver );
     
    13011301                ast::ptr< ast::FunctionDecl > ret = functionDecl;
    13021302                for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {
    1303                         const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i];
     1303                        const ast::ptr< ast::DeclWithType > & d = functionDecl->type->params[i];
    13041304
    13051305                        if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {
     
    13181318                        }
    13191319                }
    1320                 return ret.get();
     1320                return ret.release();
    13211321        }
    13221322
     
    13411341                // in case we decide to allow nested enums
    13421342                GuardValue( inEnumDecl );
    1343                 inEnumDecl = false;
     1343                inEnumDecl = true;
    13441344        }
    13451345
  • src/ResolvExpr/SatisfyAssertions.cpp

    r057298e r7030dab  
    99// Author           : Aaron B. Moss
    1010// Created On       : Mon Jun 10 17:45:00 2019
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Mon Jun 10 17:45:00 2019
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Oct  1 13:56:00 2019
     13// Update Count     : 2
    1414//
    1515
     
    299299                        Cost cost;
    300300
    301                         OutType( 
    302                                 const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 
     301                        OutType(
     302                                const ast::TypeEnvironment & e, const ast::OpenVarSet & o,
    303303                                const std::vector< DeferRef > & as, const ast::SymbolTable & symtab )
    304304                        : env( e ), open( o ), assns( as ), cost( Cost::zero ) {
     
    306306                                for ( const DeferRef & assn : assns ) {
    307307                                        // compute conversion cost from satisfying decl to assertion
    308                                         cost += computeConversionCost( 
    309                                                 assn.match.adjType, assn.decl->get_type(), symtab, env );
    310                                        
     308                                        cost += computeConversionCost(
     309                                                assn.match.adjType, assn.decl->get_type(), false, symtab, env );
     310
    311311                                        // mark vars+specialization on function-type assertions
    312                                         const ast::FunctionType * func = 
     312                                        const ast::FunctionType * func =
    313313                                                GenPoly::getFunctionType( assn.match.cdata.id->get_type() );
    314314                                        if ( ! func ) continue;
     
    317317                                                cost.decSpec( specCost( param->get_type() ) );
    318318                                        }
    319                                        
     319
    320320                                        cost.incVar( func->forall.size() );
    321                                        
     321
    322322                                        for ( const ast::TypeDecl * td : func->forall ) {
    323323                                                cost.decSpec( td->assertions.size() );
     
    329329                };
    330330
    331                 CandidateEnvMerger( 
    332                         const ast::TypeEnvironment & env, const ast::OpenVarSet & open, 
     331                CandidateEnvMerger(
     332                        const ast::TypeEnvironment & env, const ast::OpenVarSet & open,
    333333                        const ast::SymbolTable & syms )
    334334                : crnt(), envs{ env }, opens{ open }, symtab( syms ) {}
  • src/ResolvExpr/SatisfyAssertions.hpp

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

    r057298e r7030dab  
    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

    r057298e r7030dab  
    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
     
    943933
    944934        private:
    945                 template< typename RefType >
    946                 const RefType * handleRefType( const RefType * inst, const ast::Type * other ) {
     935                // Returns: other, cast as XInstType
     936                // Assigns this->result: whether types are compatible (up to generic parameters)
     937                template< typename XInstType >
     938                const XInstType * handleRefType( const XInstType * inst, const ast::Type * other ) {
    947939                        // check that the other type is compatible and named the same
    948                         auto otherInst = dynamic_cast< const RefType * >( other );
    949                         result = otherInst && inst->name == otherInst->name;
     940                        auto otherInst = dynamic_cast< const XInstType * >( other );
     941                        this->result = otherInst && inst->name == otherInst->name;
    950942                        return otherInst;
    951943                }
     
    968960                }
    969961
    970                 template< typename RefType >
    971                 void handleGenericRefType( const RefType * inst, const ast::Type * other ) {
     962                template< typename XInstType >
     963                void handleGenericRefType( const XInstType * inst, const ast::Type * other ) {
    972964                        // check that other type is compatible and named the same
    973                         const RefType * inst2 = handleRefType( inst, other );
    974                         if ( ! inst2 ) return;
     965                        const XInstType * otherInst = handleRefType( inst, other );
     966                        if ( ! this->result ) return;
    975967
    976968                        // check that parameters of types unify, if any
    977969                        const std::vector< ast::ptr< ast::Expr > > & params = inst->params;
    978                         const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params;
     970                        const std::vector< ast::ptr< ast::Expr > > & params2 = otherInst->params;
    979971
    980972                        auto it = params.begin();
     
    12021194                // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and
    12031195                // 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 );
     1196                ast::Type * t1 = shallowCopy(type1.get());
     1197                ast::Type * t2 = shallowCopy(type2.get());
     1198                t1->qualifiers = {};
     1199                t2->qualifiers = {};
     1200                ast::ptr< ast::Type > t1_(t1);
     1201                ast::ptr< ast::Type > t2_(t2);
    12071202
    12081203                if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
    1209                         t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
    1210 
    12111204                        // if exact unification on unqualified types, try to merge qualifiers
    12121205                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
    1213                                 common = type1;
    1214                                 reset_qualifiers( common, q1 | q2 );
     1206                                t1->qualifiers = q1 | q2;
     1207                                common = t1;
    12151208                                return true;
    12161209                        } else {
     
    12191212
    12201213                } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {
    1221                         t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
    1222 
    12231214                        // no exact unification, but common type
    1224                         reset_qualifiers( common, q1 | q2 );
     1215                        auto c = shallowCopy(common.get());
     1216                        c->qualifiers = q1 | q2;
     1217                        common = c;
    12251218                        return true;
    12261219                } else {
  • src/ResolvExpr/typeops.h

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

    r057298e r7030dab  
    2121
    2222#include "AST/Decl.hpp"
     23#include "AST/Eval.hpp"
    2324#include "AST/Expr.hpp"
    2425#include "AST/Init.hpp"
     
    265266                }
    266267
    267                 ast::ptr< ast::Expr > begin, end, cmp, update;
     268                ast::ptr< ast::Expr > begin, end;
     269                std::string cmp, update;
    268270
    269271                if ( forward ) {
     
    271273                        begin = ast::ConstantExpr::from_int( loc, 0 );
    272274                        end = array->dimension;
    273                         cmp = new ast::NameExpr{ loc, "?<?" };
    274                         update = new ast::NameExpr{ loc, "++?" };
     275                        cmp = "?<?";
     276                        update = "++?";
    275277                } else {
    276278                        // generate: for ( int i = N-1; i >= 0; --i )
    277                         begin = new ast::UntypedExpr{
    278                                 loc, new ast::NameExpr{ loc, "?-?" },
    279                                 { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } };
     279                        begin = ast::call(
     280                                loc, "?-?", array->dimension, ast::ConstantExpr::from_int( loc, 1 ) );
    280281                        end = ast::ConstantExpr::from_int( loc, 0 );
    281                         cmp = new ast::NameExpr{ loc, "?>=?" };
    282                         update = new ast::NameExpr{ loc, "--?" };
     282                        cmp = "?>=?";
     283                        update = "--?";
    283284                }
    284285
     
    286287                        loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },
    287288                        new ast::SingleInit{ loc, begin } };
    288                
    289                 ast::ptr< ast::Expr > cond = new ast::UntypedExpr{
    290                         loc, cmp, { new ast::VariableExpr{ loc, index }, end } };
    291                
    292                 ast::ptr< ast::Expr > inc = new ast::UntypedExpr{
    293                         loc, update, { new ast::VariableExpr{ loc, index } } };
    294                
    295                 ast::ptr< ast::Expr > dstIndex = new ast::UntypedExpr{
    296                         loc, new ast::NameExpr{ loc, "?[?]" },
    297                         { dstParam, new ast::VariableExpr{ loc, index } } };
     289                ast::ptr< ast::Expr > indexVar = new ast::VariableExpr{ loc, index };
     290               
     291                ast::ptr< ast::Expr > cond = ast::call( loc, cmp, indexVar, end );
     292               
     293                ast::ptr< ast::Expr > inc = ast::call( loc, update, indexVar );
     294               
     295                ast::ptr< ast::Expr > dstIndex = ast::call( loc, "?[?]", dstParam, indexVar );
    298296               
    299297                // srcParam must keep track of the array indices to build the source parameter and/or
    300298                // array list initializer
    301                 srcParam.addArrayIndex( new ast::VariableExpr{ loc, index }, array->dimension );
     299                srcParam.addArrayIndex( indexVar, array->dimension );
    302300
    303301                // for stmt's body, eventually containing call
     
    385383                if ( isUnnamedBitfield( obj ) ) return {};
    386384
    387                 ast::ptr< ast::Type > addCast = nullptr;
     385                ast::ptr< ast::Type > addCast;
    388386                if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
    389387                        assert( dstParam->result );
  • src/SynTree/Statement.h

    r057298e r7030dab  
    518518class ImplicitCtorDtorStmt : public Statement {
    519519  public:
    520         // Non-owned pointer to the constructor/destructor statement
     520        // the constructor/destructor call statement; owned here for a while, eventually transferred elsewhere
    521521        Statement * callStmt;
    522522
  • src/Tuples/Explode.cc

    r057298e r7030dab  
    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

    r057298e r7030dab  
    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

    r057298e r7030dab  
    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/Tuples/TupleExpansion.cc

    r057298e r7030dab  
    323323                std::vector<ast::ptr<ast::Type>> types;
    324324                ast::CV::Qualifiers quals{
    325                         ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Lvalue |
     325                        ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict |
    326326                        ast