Changes in / [665f432:9802f4c]


Ignore:
Files:
6 added
1 deleted
47 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Attribute.hpp

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

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

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

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

    r665f432 r9802f4c  
    1010// Created On       : Wed May 15 17:00:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Created On       : Thr Jun 13 13:38:00 2019
    13 // Update Count     : 2
     12// Created On       : Fri Oct  4 15:34:00 2019
     13// Update Count     : 4
    1414//
    1515
     
    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 {
     
    138155CastExpr::CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g )
    139156: Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {}
     157
     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}
    140162
    141163// --- KeywordCastExpr
     
    152174}
    153175
     176// --- UntypedMemberExpr
     177
     178bool UntypedMemberExpr::get_lvalue() const {
     179        return aggregate->get_lvalue();
     180}
     181
    154182// --- MemberExpr
    155183
     
    160188        assert( aggregate->result );
    161189
    162         // take ownership of member type
    163         result = mem->get_type();
     190        // Deep copy on result type avoids mutation on transitively multiply referenced object.
     191        //
     192        // Example, adapted from parts of builtins and bootloader:
     193        //
     194        // forall(dtype T)
     195        // struct __Destructor {
     196        //   T * object;
     197        //   void (*dtor)(T *);
     198        // };
     199        //
     200        // forall(dtype S)
     201        // void foo(__Destructor(S) &d) {
     202        //   if (d.dtor) {  // here
     203        //   }
     204        // }
     205        //
     206        // Let e be the "d.dtor" guard espression, which is MemberExpr after resolve.  Let d be the
     207        // declaration of member __Destructor.dtor (an ObjectDecl), as accessed via the top-level
     208        // declaration of __Destructor.  Consider the types e.result and d.type.  In the old AST, one
     209        // is a clone of the other.  Ordinary new-AST use would set them up as a multiply-referenced
     210        // object.
     211        //
     212        // e.result: PointerType
     213        // .base: FunctionType
     214        // .params.front(): ObjectDecl, the anonymous parameter of type T*
     215        // .type: PointerType
     216        // .base: TypeInstType
     217        // let x = that
     218        // let y = similar, except start from d.type
     219        //
     220        // Consider two code lines down, genericSubstitution(...).apply(result).
     221        //
     222        // Applying this chosen-candidate's type substitution means modifying x, substituting
     223        // S for T.  This mutation should affect x and not y.
     224
     225        result = deepCopy(mem->get_type());
     226
    164227        // substitute aggregate generic parameters into member type
    165228        genericSubstitution( aggregate->result ).apply( result );
    166         // ensure lvalue and appropriate restrictions from aggregate type
    167         add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue );
     229        // ensure appropriate restrictions from aggregate type
     230        add_qualifiers( result, aggregate->result->qualifiers );
     231}
     232
     233MemberExpr::MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
     234    MemberExpr::NoOpConstruction overloadSelector )
     235: Expr( loc ), member( mem ), aggregate( agg ) {
     236        assert( member );
     237        assert( aggregate );
     238        assert( aggregate->result );
     239        (void) overloadSelector;
     240}
     241
     242bool MemberExpr::get_lvalue() const {
     243        // This is actually wrong by C, but it works with our current set-up.
     244        return true;
    168245}
    169246
     
    177254        assert( var );
    178255        assert( var->get_type() );
    179         result = var->get_type();
    180         add_qualifiers( result, CV::Lvalue );
     256        result = shallowCopy( var->get_type() );
     257}
     258
     259bool VariableExpr::get_lvalue() const {
     260        // It isn't always an lvalue, but it is never an rvalue.
     261        return true;
    181262}
    182263
     
    265346: Expr( loc, new BasicType{ BasicType::SignedInt } ), arg1( a1 ), arg2( a2 ), isAnd( ia ) {}
    266347
     348// --- CommaExpr
     349bool CommaExpr::get_lvalue() const {
     350        // This is wrong by C, but the current implementation uses it.
     351        // (ex: Specialize, Lvalue and Box)
     352        return arg2->get_lvalue();
     353}
     354
    267355// --- ConstructorExpr
    268356
     
    283371        assert( t && i );
    284372        result = t;
    285         add_qualifiers( result, CV::Lvalue );
     373}
     374
     375bool CompoundLiteralExpr::get_lvalue() const {
     376        return true;
    286377}
    287378
     
    300391        // like MemberExpr, TupleIndexExpr is always an lvalue
    301392        result = type->types[ index ];
    302         add_qualifiers( result, CV::Lvalue );
     393}
     394
     395bool TupleIndexExpr::get_lvalue() const {
     396        return tuple->get_lvalue();
    303397}
    304398
  • src/AST/Expr.hpp

    r665f432 r9802f4c  
    99// Author           : Aaron B. Moss
    1010// Created On       : Fri May 10 10:30:00 2019
    11 // Last Modified By : Aaron B. Moss
    12 // Created On       : Fri May 10 10:30:00 2019
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Created On       : Thr Sep 26 12:51:00 2019
     13// Update Count     : 2
    1414//
    1515
     
    3030
    3131// Must be included in *all* AST classes; should be #undef'd at the end of the file
    32 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     32#define MUTATE_FRIEND \
     33    template<typename node_t> friend node_t * mutate(const node_t * node); \
     34        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
     35
    3336
    3437class ConverterOldToNew;
     
    184187
    185188        Expr * set_extension( bool ex ) { extension = ex; return this; }
     189        virtual bool get_lvalue() const;
    186190
    187191        virtual const Expr * accept( Visitor & v ) const override = 0;
     
    200204        ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} );
    201205
     206        bool get_lvalue() const final;
     207
    202208        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    203209private:
     
    214220        UntypedExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} )
    215221        : Expr( loc ), func( f ), args( std::move(as) ) {}
     222
     223        bool get_lvalue() const final;
    216224
    217225        /// Creates a new dereference expression
     
    290298        CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {}
    291299
     300        bool get_lvalue() const final;
     301
    292302        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    293303private:
     
    337347        : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); }
    338348
     349        bool get_lvalue() const final;
     350
    339351        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    340352private:
     
    351363        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg );
    352364
     365        bool get_lvalue() const final;
     366
    353367        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    354368private:
    355369        MemberExpr * clone() const override { return new MemberExpr{ *this }; }
    356370        MUTATE_FRIEND
     371
     372        // Custructor overload meant only for AST conversion
     373        enum NoOpConstruction { NoOpConstructionChosen };
     374        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
     375            NoOpConstruction overloadSelector );
     376        friend class ::ConverterOldToNew;
     377        friend class ::ConverterNewToOld;
    357378};
    358379
     
    364385        VariableExpr( const CodeLocation & loc );
    365386        VariableExpr( const CodeLocation & loc, const DeclWithType * v );
     387
     388        bool get_lvalue() const final;
    366389
    367390        /// generates a function pointer for a given function
     
    531554
    532555        CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
    533         : Expr( loc ), arg1( a1 ), arg2( a2 ) {}
     556        : Expr( loc ), arg1( a1 ), arg2( a2 ) {
     557                this->result = a2->result;
     558        }
     559
     560        bool get_lvalue() const final;
    534561
    535562        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    604631        CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i );
    605632
     633        bool get_lvalue() const final;
     634
    606635        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    607636private:
     
    659688
    660689        TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i );
     690
     691        bool get_lvalue() const final;
    661692
    662693        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Init.hpp

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

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

    r665f432 r9802f4c  
    127127                        , decltype( node->accept(*this) )
    128128                >::type
    129 
    130129        {
    131130                __pedantic_pass_assert( __visit_children() );
    132                 __pedantic_pass_assert( expr );
     131                __pedantic_pass_assert( node );
    133132
    134133                static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR");
     
    323322        }
    324323
     324
     325        template< typename pass_t >
     326        template< typename node_t >
     327        void ast::Pass< pass_t >::mutate_forall( const node_t *& node ) {
     328                if ( auto subs = __pass::forall::subs( pass, 0 ) ) {
     329                        // tracking TypeDecl substitution, full clone
     330                        if ( node->forall.empty() ) return;
     331
     332                        node_t * mut = mutate( node );
     333                        mut->forall = subs->clone( node->forall, *this );
     334                        node = mut;
     335                } else {
     336                        // not tracking TypeDecl substitution, just mutate
     337                        maybe_accept( node, &node_t::forall );
     338                }
     339        }
    325340}
    326341
     
    429444                        guard_symtab guard { *this };
    430445                        // implicit add __func__ identifier as specified in the C manual 6.4.2.2
    431                         static ast::ObjectDecl func(
    432                                 node->location, "__func__",
    433                                 new ast::ArrayType(
    434                                         new ast::BasicType( ast::BasicType::Char, ast::CV::Qualifiers( ast::CV::Const ) ),
     446                        static ast::ptr< ast::ObjectDecl > func{ new ast::ObjectDecl{
     447                                CodeLocation{}, "__func__",
     448                                new ast::ArrayType{
     449                                        new ast::BasicType{ ast::BasicType::Char, ast::CV::Const },
    435450                                        nullptr, VariableLen, DynamicDim
    436                                 )
    437                         );
    438                         __pass::symtab::addId( pass, 0, &func );
     451                                }
     452                        } };
     453                        __pass::symtab::addId( pass, 0, func );
    439454                        VISIT(
    440455                                maybe_accept( node, &FunctionDecl::type );
     
    610625        VISIT({
    611626                // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    612                 auto guard1 = makeFuncGuard( [this, inFunction = this->inFunction]() {
    613                         if ( ! inFunction ) __pass::symtab::enter(pass, 0);
    614                 }, [this, inFunction = this->inFunction]() {
    615                         if ( ! inFunction ) __pass::symtab::leave(pass, 0);
     627                auto guard1 = makeFuncGuard( [this, inFunctionCpy = this->inFunction]() {
     628                        if ( ! inFunctionCpy ) __pass::symtab::enter(pass, 0);
     629                }, [this, inFunctionCpy = this->inFunction]() {
     630                        if ( ! inFunctionCpy ) __pass::symtab::leave(pass, 0);
    616631                });
    617632                ValueGuard< bool > guard2( inFunction );
     
    938953        // For now this isn't visited, it is unclear if this causes problem
    939954        // if all tests are known to pass, remove this code
    940         // VISIT(
    941         //      maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
    942         // )
     955        VISIT(
     956                maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
     957        )
    943958
    944959        VISIT_END( Stmt, node );
     
    16661681        VISIT_START( node );
    16671682
    1668         VISIT(
    1669                 maybe_accept( node, &FunctionType::forall  );
     1683        VISIT({
     1684                guard_forall_subs forall_guard { *this, node };
     1685                mutate_forall( node );
    16701686                maybe_accept( node, &FunctionType::returns );
    16711687                maybe_accept( node, &FunctionType::params  );
    1672         )
     1688        })
    16731689
    16741690        VISIT_END( Type, node );
     
    16851701        VISIT({
    16861702                guard_symtab guard { *this };
    1687                 maybe_accept( node, &StructInstType::forall );
     1703                guard_forall_subs forall_guard { *this, node };
     1704                mutate_forall( node );
    16881705                maybe_accept( node, &StructInstType::params );
    16891706        })
     
    16981715        VISIT_START( node );
    16991716
    1700         __pass::symtab::addStruct( pass, 0, node->name );
    1701 
    1702         {
     1717        __pass::symtab::addUnion( pass, 0, node->name );
     1718
     1719        VISIT({
    17031720                guard_symtab guard { *this };
    1704                 maybe_accept( node, &UnionInstType::forall );
     1721                guard_forall_subs forall_guard { *this, node };
     1722                mutate_forall( node );
    17051723                maybe_accept( node, &UnionInstType::params );
    1706         }
     1724        })
    17071725
    17081726        VISIT_END( Type, node );
     
    17151733        VISIT_START( node );
    17161734
    1717         VISIT(
    1718                 maybe_accept( node, &EnumInstType::forall );
     1735        VISIT({
     1736                guard_forall_subs forall_guard { *this, node };
     1737                mutate_forall( node );
    17191738                maybe_accept( node, &EnumInstType::params );
    1720         )
     1739        })
    17211740
    17221741        VISIT_END( Type, node );
     
    17291748        VISIT_START( node );
    17301749
    1731         VISIT(
    1732                 maybe_accept( node, &TraitInstType::forall );
     1750        VISIT({
     1751                guard_forall_subs forall_guard { *this, node };
     1752                mutate_forall( node );
    17331753                maybe_accept( node, &TraitInstType::params );
    1734         )
     1754        })
    17351755
    17361756        VISIT_END( Type, node );
     
    17441764
    17451765        VISIT(
    1746                 maybe_accept( node, &TypeInstType::forall );
    1747                 maybe_accept( node, &TypeInstType::params );
     1766                {
     1767                        guard_forall_subs forall_guard { *this, node };
     1768                        mutate_forall( node );
     1769                        maybe_accept( node, &TypeInstType::params );
     1770                }
     1771                // ensure that base re-bound if doing substitution
     1772                __pass::forall::replace( pass, 0, node );
    17481773        )
    17491774
     
    18941919                                guard_symtab guard { *this };
    18951920                                auto new_node = p.second->accept( *this );
    1896                                 if (new_node != p.second) mutated = false;
     1921                                if (new_node != p.second) mutated = true;
    18971922                                new_map.insert({ p.first, new_node });
    18981923                        }
     
    19101935                                guard_symtab guard { *this };
    19111936                                auto new_node = p.second->accept( *this );
    1912                                 if (new_node != p.second) mutated = false;
     1937                                if (new_node != p.second) mutated = true;
    19131938                                new_map.insert({ p.first, new_node });
    19141939                        }
  • src/AST/Pass.proto.hpp

    r665f432 r9802f4c  
    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

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

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

    r665f432 r9802f4c  
    3030
    3131// Must be included in *all* AST classes; should be #undef'd at the end of the file
    32 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     32#define MUTATE_FRIEND \
     33    template<typename node_t> friend node_t * mutate(const node_t * node); \
     34        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3335
    3436namespace ast {
     37
     38template< typename T > class Pass;
     39
     40struct ForallSubstitutor;
    3541
    3642class Type : public Node {
     
    4551        bool is_volatile() const { return qualifiers.is_volatile; }
    4652        bool is_restrict() const { return qualifiers.is_restrict; }
    47         bool is_lvalue() const { return qualifiers.is_lvalue; }
    4853        bool is_mutex() const { return qualifiers.is_mutex; }
    4954        bool is_atomic() const { return qualifiers.is_atomic; }
     
    5257        Type * set_volatile( bool v ) { qualifiers.is_volatile = v; return this; }
    5358        Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; }
    54         Type * set_lvalue( bool v ) { qualifiers.is_lvalue = v; return this; }
    5559        Type * set_mutex( bool v ) { qualifiers.is_mutex = v; return this; }
    5660        Type * set_atomic( bool v ) { qualifiers.is_atomic = v; return this; }
     
    164168        static const char *typeNames[];
    165169
    166         BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 
     170        BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    167171        : Type(q, std::move(as)), kind(k) {}
    168172
     
    266270/// Base type for potentially forall-qualified types
    267271class ParameterizedType : public Type {
     272protected:
     273        /// initializes forall with substitutor
     274        void initWithSub( const ParameterizedType & o, Pass< ForallSubstitutor > & sub );
    268275public:
    269276        using ForallList = std::vector<ptr<TypeDecl>>;
     
    277284        ParameterizedType( CV::Qualifiers q, std::vector<ptr<Attribute>> && as = {} )
    278285        : Type(q, std::move(as)), forall() {}
     286
     287        // enforce use of ForallSubstitutor to copy parameterized type
     288        ParameterizedType( const ParameterizedType & ) = delete;
     289
     290        ParameterizedType( ParameterizedType && ) = default;
     291
     292        // no need to change destructor, and operator= deleted in Node
    279293
    280294private:
     
    302316        : ParameterizedType(q), returns(), params(), isVarArgs(va) {}
    303317
     318        FunctionType( const FunctionType & o );
     319
    304320        /// true if either the parameters or return values contain a tttype
    305321        bool isTtype() const;
     
    315331/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
    316332class ReferenceToType : public ParameterizedType {
     333protected:
     334        /// Initializes forall and parameters based on substitutor
     335        void initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub );
    317336public:
    318337        std::vector<ptr<Expr>> params;
     
    320339        bool hoistType = false;
    321340
    322         ReferenceToType( const std::string& n, CV::Qualifiers q = {},
    323                 std::vector<ptr<Attribute>> && as = {} )
     341        ReferenceToType(
     342                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    324343        : ParameterizedType(q, std::move(as)), params(), name(n) {}
     344
     345        ReferenceToType( const ReferenceToType & o );
    325346
    326347        /// Gets aggregate declaration this type refers to
     
    339360        readonly<StructDecl> base;
    340361
    341         StructInstType( const std::string& n, CV::Qualifiers q = {},
    342                 std::vector<ptr<Attribute>> && as = {} )
     362        StructInstType(
     363                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    343364        : ReferenceToType( n, q, std::move(as) ), base() {}
    344         StructInstType( const StructDecl * b, CV::Qualifiers q = {},
    345                 std::vector<ptr<Attribute>> && as = {} );
     365
     366        StructInstType(
     367                const StructDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    346368
    347369        bool isComplete() const override;
     
    360382        readonly<UnionDecl> base;
    361383
    362         UnionInstType( const std::string& n, CV::Qualifiers q = {},
    363                 std::vector<ptr<Attribute>> && as = {} )
     384        UnionInstType(
     385                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    364386        : ReferenceToType( n, q, std::move(as) ), base() {}
    365         UnionInstType( const UnionDecl * b, CV::Qualifiers q = {},
    366                 std::vector<ptr<Attribute>> && as = {} );
     387
     388        UnionInstType(
     389                const UnionDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    367390
    368391        bool isComplete() const override;
     
    381404        readonly<EnumDecl> base;
    382405
    383         EnumInstType( const std::string& n, CV::Qualifiers q = {},
    384                 std::vector<ptr<Attribute>> && as = {} )
     406        EnumInstType(
     407                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    385408        : ReferenceToType( n, q, std::move(as) ), base() {}
    386         EnumInstType( const EnumDecl * b, CV::Qualifiers q = {},
    387                 std::vector<ptr<Attribute>> && as = {} );
     409
     410        EnumInstType(
     411                const EnumDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    388412
    389413        bool isComplete() const override;
     
    402426        readonly<TraitDecl> base;
    403427
    404         TraitInstType( const std::string& n, CV::Qualifiers q = {},
    405                 std::vector<ptr<Attribute>> && as = {} )
     428        TraitInstType(
     429                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    406430        : ReferenceToType( n, q, std::move(as) ), base() {}
    407         TraitInstType( const TraitDecl * b, CV::Qualifiers q = {},
    408                 std::vector<ptr<Attribute>> && as = {} );
     431
     432        TraitInstType(
     433                const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    409434
    410435        // not meaningful for TraitInstType
     
    425450        TypeVar::Kind kind;
    426451
    427         TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
     452        TypeInstType(
     453                const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
    428454                std::vector<ptr<Attribute>> && as = {} )
    429455        : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
    430         TypeInstType( const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {},
     456
     457        TypeInstType(
     458                const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {},
    431459                std::vector<ptr<Attribute>> && as = {} )
    432460        : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
     461
     462        TypeInstType( const TypeInstType & o );
    433463
    434464        /// sets `base`, updating `kind` correctly
  • src/AST/TypeEnvironment.hpp

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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    169169        AST/Convert.$(OBJEXT) AST/Decl.$(OBJEXT) \
    170170        AST/DeclReplacer.$(OBJEXT) AST/Expr.$(OBJEXT) \
     171        AST/ForallSubstitutionTable.$(OBJEXT) \
    171172        AST/GenericSubstitution.$(OBJEXT) AST/Init.$(OBJEXT) \
    172173        AST/LinkageSpec.$(OBJEXT) AST/Node.$(OBJEXT) \
     
    590591        AST/DeclReplacer.cpp \
    591592        AST/Expr.cpp \
     593        AST/ForallSubstitutionTable.cpp \
    592594        AST/GenericSubstitution.cpp \
    593595        AST/Init.cpp \
     
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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;
     
    602602
    603603                Finder( CandidateFinder & f )
    604                 : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
     604                : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
    605605                  targetType( f.targetType ) {}
    606                
     606
    607607                void previsit( const ast::Node * ) { visit_children = false; }
    608608
     
    639639
    640640                /// Completes a function candidate with arguments located
    641                 void validateFunctionCandidate( 
    642                         const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 
    643                         CandidateList & out 
     641                void validateFunctionCandidate(
     642                        const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,
     643                        CandidateList & out
    644644                ) {
    645                         ast::ApplicationExpr * appExpr = 
     645                        ast::ApplicationExpr * appExpr =
    646646                                new ast::ApplicationExpr{ func->expr->location, func->expr };
    647647                        // sum cost and accumulate arguments
     
    657657                        appExpr->args = move( vargs );
    658658                        // build and validate new candidate
    659                         auto newCand = 
     659                        auto newCand =
    660660                                std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );
    661661                        PRINT(
     
    669669                /// Builds a list of candidates for a function, storing them in out
    670670                void makeFunctionCandidates(
    671                         const CandidateRef & func, const ast::FunctionType * funcType, 
     671                        const CandidateRef & func, const ast::FunctionType * funcType,
    672672                        const ExplodedArgs_new & args, CandidateList & out
    673673                ) {
     
    676676                        ast::TypeEnvironment funcEnv{ func->env };
    677677                        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
     678                        // add all type variables as open variables now so that those not used in the
     679                        // parameter list are still considered open
    680680                        funcEnv.add( funcType->forall );
    681681
     
    683683                                // attempt to narrow based on expected target type
    684684                                const ast::Type * returnType = funcType->returns.front()->get_type();
    685                                 if ( ! unify( 
    686                                         returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 
     685                                if ( ! unify(
     686                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
    687687                                ) {
    688688                                        // unification failed, do not pursue this candidate
     
    698698                        for ( const ast::DeclWithType * param : funcType->params ) {
    699699                                auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
    700                                 // Try adding the arguments corresponding to the current parameter to the existing 
     700                                // Try adding the arguments corresponding to the current parameter to the existing
    701701                                // matches
    702                                 if ( ! instantiateArgument( 
     702                                if ( ! instantiateArgument(
    703703                                        obj->type, obj->init, args, results, genStart, symtab ) ) return;
    704704                        }
     
    750750                                                        if ( expl.exprs.empty() ) {
    751751                                                                results.emplace_back(
    752                                                                         results[i], move( env ), copy( results[i].need ), 
    753                                                                         copy( results[i].have ), move( open ), nextArg + 1, 
     752                                                                        results[i], move( env ), copy( results[i].need ),
     753                                                                        copy( results[i].have ), move( open ), nextArg + 1,
    754754                                                                        expl.cost );
    755755
     
    760760                                                        results.emplace_back(
    761761                                                                i, expl.exprs.front(), move( env ), copy( results[i].need ),
    762                                                                 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 
     762                                                                copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost,
    763763                                                                expl.exprs.size() == 1 ? 0 : 1, j );
    764764                                                }
     
    780780                /// Adds implicit struct-conversions to the alternative list
    781781                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 
     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
    784784                        // base type to treat the aggregate as the referenced value
    785785                        ast::ptr< ast::Expr > aggrExpr( cand->expr );
    786786                        ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;
    787787                        cand->env.apply( aggrType );
    788                        
     788
    789789                        if ( aggrType.as< ast::ReferenceType >() ) {
    790790                                aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };
     
    799799
    800800                /// 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 
     801                void addAggMembers(
     802                        const ast::ReferenceToType * aggrInst, const ast::Expr * expr,
     803                        const Candidate & cand, const Cost & addedCost, const std::string & name
    804804                ) {
    805805                        for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {
    806806                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );
    807                                 CandidateRef newCand = std::make_shared<Candidate>( 
     807                                CandidateRef newCand = std::make_shared<Candidate>(
    808808                                        cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
    809                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     809                                // add anonymous member interpretations whenever an aggregate value type is seen
    810810                                // as a member expression
    811811                                addAnonConversions( newCand );
     
    815815
    816816                /// 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 
     817                void addTupleMembers(
     818                        const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,
     819                        const Cost & addedCost, const ast::Expr * member
    820820                ) {
    821821                        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 
     822                                // get the value of the constant expression as an int, must be between 0 and the
    823823                                // length of the tuple to have meaning
    824824                                long long val = constantExpr->intValue();
    825825                                if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    826826                                        addCandidate(
    827                                                 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 
     827                                                cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },
    828828                                                addedCost );
    829829                                }
     
    837837                        if ( funcFinder.candidates.empty() ) return;
    838838
    839                         std::vector< CandidateFinder > argCandidates = 
     839                        std::vector< CandidateFinder > argCandidates =
    840840                                selfFinder.findSubExprs( untypedExpr->args );
    841                        
     841
    842842                        // take care of possible tuple assignments
    843843                        // if not tuple assignment, handled as normal function call
     
    877877                                                if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    878878                                                        CandidateRef newFunc{ new Candidate{ *func } };
    879                                                         newFunc->expr = 
     879                                                        newFunc->expr =
    880880                                                                referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    881881                                                        makeFunctionCandidates( newFunc, function, argExpansions, found );
    882882                                                }
    883                                         } else if ( 
    884                                                 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 
     883                                        } else if (
     884                                                auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
    885885                                        ) {
    886886                                                if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) {
    887887                                                        if ( auto function = clz->bound.as< ast::FunctionType >() ) {
    888888                                                                CandidateRef newFunc{ new Candidate{ *func } };
    889                                                                 newFunc->expr = 
     889                                                                newFunc->expr =
    890890                                                                        referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    891891                                                                makeFunctionCandidates( newFunc, function, argExpansions, found );
     
    901901                                std::vector< ExplodedArg > funcE;
    902902                                funcE.reserve( funcFinder.candidates.size() );
    903                                 for ( const CandidateRef & func : funcFinder ) { 
     903                                for ( const CandidateRef & func : funcFinder ) {
    904904                                        funcE.emplace_back( *func, symtab );
    905905                                }
     
    913913                                                        if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    914914                                                                CandidateRef newOp{ new Candidate{ *op} };
    915                                                                 newOp->expr = 
     915                                                                newOp->expr =
    916916                                                                        referenceToRvalueConversion( newOp->expr, newOp->cost );
    917917                                                                makeFunctionCandidates( newOp, function, argExpansions, found );
     
    922922                        }
    923923
    924                         // Implement SFINAE; resolution errors are only errors if there aren't any non-error 
     924                        // Implement SFINAE; resolution errors are only errors if there aren't any non-error
    925925                        // candidates
    926926                        if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
     
    934934                                        auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
    935935                                        auto function = pointer->base.strict_as< ast::FunctionType >();
    936                                        
     936
    937937                                        std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;
    938938                                        std::cerr << "parameters are:" << std::endl;
     
    957957                        promoteCvtCost( winners );
    958958
    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 
     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
    961961                        // `findMinCost`, since anon conversions are never the cheapest
    962962                        for ( const CandidateRef & c : winners ) {
     
    966966
    967967                        if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
    968                                 // If resolution is unsuccessful with a target type, try again without, since it 
     968                                // If resolution is unsuccessful with a target type, try again without, since it
    969969                                // will sometimes succeed when it wouldn't with a target type binding.
    970970                                // For example:
     
    983983                /// true if expression is an lvalue
    984984                static bool isLvalue( const ast::Expr * x ) {
    985                         return x->result && ( x->result->is_lvalue() || x->result.as< ast::ReferenceType >() );
     985                        return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() );
    986986                }
    987987
     
    10161016                                cand->env.extractOpenVars( open );
    10171017
    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 
     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
    10211021                                // has fewer results than there are types to cast to.
    10221022                                int discardedValues = cand->expr->result->size() - toType->size();
     
    10251025                                // unification run for side-effects
    10261026                                unify( toType, cand->expr->result, cand->env, need, have, open, symtab );
    1027                                 Cost thisCost = castCost( cand->expr->result, toType, symtab, cand->env );
     1027                                Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1028                                                symtab, cand->env );
    10281029                                PRINT(
    10291030                                        std::cerr << "working on cast with result: " << toType << std::endl;
     
    10371038                                        // count one safe conversion for each value that is thrown away
    10381039                                        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, 
     1040                                        CandidateRef newCand = std::make_shared<Candidate>(
     1041                                                restructureCast( cand->expr, toType, castExpr->isGenerated ),
     1042                                                copy( cand->env ), move( open ), move( need ), cand->cost,
    10421043                                                cand->cost + thisCost );
    10431044                                        inferParameters( newCand, matches );
     
    10571058                        finder.find( castExpr->arg, ResolvMode::withoutPrune() );
    10581059                        for ( CandidateRef & r : finder.candidates ) {
    1059                                 addCandidate( 
    1060                                         *r, 
     1060                                addCandidate(
     1061                                        *r,
    10611062                                        new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
    10621063                        }
     
    10671068                        aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    10681069                        for ( CandidateRef & agg : aggFinder.candidates ) {
    1069                                 // it's okay for the aggregate expression to have reference type -- cast it to the 
     1070                                // it's okay for the aggregate expression to have reference type -- cast it to the
    10701071                                // base type to treat the aggregate as the referenced value
    10711072                                Cost addedCost = Cost::zero;
     
    10741075                                // find member of the given type
    10751076                                if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {
    1076                                         addAggMembers( 
     1077                                        addAggMembers(
    10771078                                                structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10781079                                } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {
    1079                                         addAggMembers( 
     1080                                        addAggMembers(
    10801081                                                unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10811082                                } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {
     
    10971098
    10981099                                CandidateRef newCand = std::make_shared<Candidate>(
    1099                                         newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 
     1100                                        newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
    11001101                                        cost );
    11011102                                PRINT(
     
    11071108                                        std::cerr << std::endl;
    11081109                                )
    1109                                 newCand->expr = ast::mutate_field( 
    1110                                         newCand->expr.get(), &ast::Expr::result, 
     1110                                newCand->expr = ast::mutate_field(
     1111                                        newCand->expr.get(), &ast::Expr::result,
    11111112                                        renameTyVars( newCand->expr->result ) );
    1112                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     1113                                // add anonymous member interpretations whenever an aggregate value type is seen
    11131114                                // as a name expression
    11141115                                addAnonConversions( newCand );
     
    11201121                        // not sufficient to just pass `variableExpr` here, type might have changed since
    11211122                        // creation
    1122                         addCandidate( 
     1123                        addCandidate(
    11231124                                new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
    11241125                }
     
    11301131                void postvisit( const ast::SizeofExpr * sizeofExpr ) {
    11311132                        if ( sizeofExpr->type ) {
    1132                                 addCandidate( 
    1133                                         new ast::SizeofExpr{ 
    1134                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 
     1133                                addCandidate(
     1134                                        new ast::SizeofExpr{
     1135                                                sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
    11351136                                        tenv );
    11361137                        } else {
     
    11411142                                CandidateList winners = findMinCost( finder.candidates );
    11421143                                if ( winners.size() != 1 ) {
    1143                                         SemanticError( 
     1144                                        SemanticError(
    11441145                                                sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );
    11451146                                }
     
    11541155                void postvisit( const ast::AlignofExpr * alignofExpr ) {
    11551156                        if ( alignofExpr->type ) {
    1156                                 addCandidate( 
    1157                                         new ast::AlignofExpr{ 
    1158                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 
     1157                                addCandidate(
     1158                                        new ast::AlignofExpr{
     1159                                                alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
    11591160                                        tenv );
    11601161                        } else {
     
    11651166                                CandidateList winners = findMinCost( finder.candidates );
    11661167                                if ( winners.size() != 1 ) {
    1167                                         SemanticError( 
     1168                                        SemanticError(
    11681169                                                alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );
    11691170                                }
     
    11721173                                choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    11731174                                choice->cost = Cost::zero;
    1174                                 addCandidate( 
     1175                                addCandidate(
    11751176                                        *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );
    11761177                        }
     
    11851186                        for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {
    11861187                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );
    1187                                 addCandidate( 
     1188                                addCandidate(
    11881189                                        new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );
    11891190                        }
     
    12181219
    12191220                                        addCandidate(
    1220                                                 new ast::LogicalExpr{ 
     1221                                                new ast::LogicalExpr{
    12211222                                                        logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
    12221223                                                move( env ), move( open ), move( need ), r1->cost + r2->cost );
     
    12561257                                                ast::AssertionSet have;
    12571258
    1258                                                 // unify true and false results, then infer parameters to produce new 
     1259                                                // unify true and false results, then infer parameters to produce new
    12591260                                                // candidates
    12601261                                                ast::ptr< ast::Type > common;
    1261                                                 if ( 
    1262                                                         unify( 
    1263                                                                 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 
    1264                                                                 common ) 
     1262                                                if (
     1263                                                        unify(
     1264                                                                r2->expr->result, r3->expr->result, env, need, have, open, symtab,
     1265                                                                common )
    12651266                                                ) {
    12661267                                                        // generate typed expression
    1267                                                         ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 
     1268                                                        ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{
    12681269                                                                conditionalExpr->location, r1->expr, r2->expr, r3->expr };
    12691270                                                        newExpr->result = common ? common : r2->expr->result;
    12701271                                                        // convert both options to result type
    12711272                                                        Cost cost = r1->cost + r2->cost + r3->cost;
    1272                                                         newExpr->arg2 = computeExpressionConversionCost( 
     1273                                                        newExpr->arg2 = computeExpressionConversionCost(
    12731274                                                                newExpr->arg2, newExpr->result, symtab, env, cost );
    12741275                                                        newExpr->arg3 = computeExpressionConversionCost(
     
    12871288                        ast::TypeEnvironment env{ tenv };
    12881289                        ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
    1289                        
     1290
    12901291                        CandidateFinder finder2{ symtab, env };
    12911292                        finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
     
    13301331
    13311332                                        ast::ptr< ast::Type > common;
    1332                                         if ( 
    1333                                                 unify( 
    1334                                                         r1->expr->result, r2->expr->result, env, need, have, open, symtab, 
    1335                                                         common ) 
     1333                                        if (
     1334                                                unify(
     1335                                                        r1->expr->result, r2->expr->result, env, need, have, open, symtab,
     1336                                                        common )
    13361337                                        ) {
    13371338                                                // generate new expression
    1338                                                 ast::RangeExpr * newExpr = 
     1339                                                ast::RangeExpr * newExpr =
    13391340                                                        new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
    13401341                                                newExpr->result = common ? common : r1->expr->result;
    13411342                                                // add candidate
    13421343                                                CandidateRef newCand = std::make_shared<Candidate>(
    1343                                                         newExpr, move( env ), move( open ), move( need ), 
     1344                                                        newExpr, move( env ), move( open ), move( need ),
    13441345                                                        r1->cost + r2->cost );
    13451346                                                inferParameters( newCand, candidates );
     
    13501351
    13511352                void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
    1352                         std::vector< CandidateFinder > subCandidates = 
     1353                        std::vector< CandidateFinder > subCandidates =
    13531354                                selfFinder.findSubExprs( tupleExpr->exprs );
    13541355                        std::vector< CandidateList > possibilities;
     
    13701371
    13711372                                addCandidate(
    1372                                         new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 
     1373                                        new ast::TupleExpr{ tupleExpr->location, move( exprs ) },
    13731374                                        move( env ), move( open ), move( need ), sumCost( subs ) );
    13741375                        }
     
    14121413                                toType = SymTab::validateType( initExpr->location, toType, symtab );
    14131414                                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. 
     1415                                // The call to find must occur inside this loop, otherwise polymorphic return
     1416                                // types are not bound to the initialization type, since return type variables are
     1417                                // only open for the duration of resolving the UntypedExpr.
    14171418                                CandidateFinder finder{ symtab, tenv, toType };
    14181419                                finder.find( initExpr->expr, ResolvMode::withAdjustment() );
     
    14261427                                        )
    14271428
    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 
     1429                                        // It is possible that a cast can throw away some values in a multiply-valued
     1430                                        // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of
     1431                                        // the subexpression results that are cast directly. The candidate is invalid
    14311432                                        // if it has fewer results than there are types to cast to.
    14321433                                        int discardedValues = cand->expr->result->size() - toType->size();
     
    14351436                                        // unification run for side-effects
    14361437                                        unify( toType, cand->expr->result, env, need, have, open, symtab );
    1437                                         Cost thisCost = castCost( cand->expr->result, toType, symtab, env );
    1438                                        
     1438                                        Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1439                                                        symtab, env );
     1440
    14391441                                        if ( thisCost != Cost::infinity ) {
    14401442                                                // count one safe conversion for each value that is thrown away
    14411443                                                thisCost.incSafe( discardedValues );
    1442                                                 CandidateRef newCand = std::make_shared<Candidate>( 
    1443                                                         new ast::InitExpr{ 
    1444                                                                 initExpr->location, restructureCast( cand->expr, toType ), 
    1445                                                                 initAlt.designation }, 
     1444                                                CandidateRef newCand = std::make_shared<Candidate>(
     1445                                                        new ast::InitExpr{
     1446                                                                initExpr->location, restructureCast( cand->expr, toType ),
     1447                                                                initAlt.designation },
    14461448                                                        copy( cand->env ), move( open ), move( need ), cand->cost, thisCost );
    14471449                                                inferParameters( newCand, matches );
     
    14691471        };
    14701472
    1471         /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 
     1473        /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
    14721474        /// return type. Skips ambiguous candidates.
    14731475        CandidateList pruneCandidates( CandidateList & candidates ) {
     
    14861488                        {
    14871489                                ast::ptr< ast::Type > newType = candidate->expr->result;
     1490                                assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());
    14881491                                candidate->env.apply( newType );
    14891492                                mangleName = Mangle::mangle( newType );
     
    14941497                                if ( candidate->cost < found->second.candidate->cost ) {
    14951498                                        PRINT(
    1496                                                 std::cerr << "cost " << candidate->cost << " beats " 
     1499                                                std::cerr << "cost " << candidate->cost << " beats "
    14971500                                                        << found->second.candidate->cost << std::endl;
    14981501                                        )
     
    15001503                                        found->second = PruneStruct{ candidate };
    15011504                                } 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 
     1505                                        // if one of the candidates contains a deleted identifier, can pick the other,
     1506                                        // since deleted expressions should not be ambiguous if there is another option
    15041507                                        // that is at least as good
    15051508                                        if ( findDeletedExpr( candidate->expr ) ) {
     
    15151518                                } else {
    15161519                                        PRINT(
    1517                                                 std::cerr << "cost " << candidate->cost << " loses to " 
     1520                                                std::cerr << "cost " << candidate->cost << " loses to "
    15181521                                                        << found->second.candidate->cost << std::endl;
    15191522                                        )
     
    15301533
    15311534                        CandidateRef cand = target.second.candidate;
    1532                        
     1535
    15331536                        ast::ptr< ast::Type > newResult = cand->expr->result;
    15341537                        cand->env.applyFree( newResult );
    15351538                        cand->expr = ast::mutate_field(
    15361539                                cand->expr.get(), &ast::Expr::result, move( newResult ) );
    1537                        
     1540
    15381541                        out.emplace_back( cand );
    15391542                }
     
    15581561                std::vector< std::string > errors;
    15591562                for ( CandidateRef & candidate : candidates ) {
    1560                         satisfyAssertions( candidate, symtab, satisfied, errors );
     1563                        satisfyAssertions( candidate, localSyms, satisfied, errors );
    15611564                }
    15621565
     
    15831586
    15841587                CandidateList pruned = pruneCandidates( candidates );
    1585                
     1588
    15861589                if ( mode.failFast && pruned.empty() ) {
    15871590                        std::ostringstream stream;
     
    16021605                )
    16031606                PRINT(
    1604                         std::cerr << "there are " << candidates.size() << " alternatives after elimination" 
     1607                        std::cerr << "there are " << candidates.size() << " alternatives after elimination"
    16051608                                << std::endl;
    16061609                )
    16071610        }
    16081611
    1609         // adjust types after pruning so that types substituted by pruneAlternatives are correctly 
     1612        // adjust types after pruning so that types substituted by pruneAlternatives are correctly
    16101613        // adjusted
    16111614        if ( mode.adjust ) {
    16121615                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 ) );
     1616                        r->expr = ast::mutate_field(
     1617                                r->expr.get(), &ast::Expr::result,
     1618                                adjustExprType( r->expr->result, r->env, localSyms ) );
    16161619                }
    16171620        }
     
    16251628}
    16261629
    1627 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 
    1628         const std::vector< ast::ptr< ast::Expr > > & xs 
     1630std::vector< CandidateFinder > CandidateFinder::findSubExprs(
     1631        const std::vector< ast::ptr< ast::Expr > > & xs
    16291632) {
    16301633        std::vector< CandidateFinder > out;
    16311634
    16321635        for ( const auto & x : xs ) {
    1633                 out.emplace_back( symtab, env );
     1636                out.emplace_back( localSyms, env );
    16341637                out.back().find( x, ResolvMode::withAdjustment() );
    1635                
     1638
    16361639                PRINT(
    16371640                        std::cerr << "findSubExprs" << std::endl;
  • src/ResolvExpr/CandidateFinder.hpp

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    10511051                        const ast::Expr * postmutate( const ast::CastExpr * castExpr ) {
    10521052                                if (
    1053                                         castExpr->isGenerated
     1053                                        castExpr->isGenerated == ast::GeneratedCast
    10541054                                        && typesCompatible( castExpr->arg->result, castExpr->result )
    10551055                                ) {
     
    11051105
    11061106                // set up and resolve expression cast to void
    1107                 ast::CastExpr * untyped = new ast::CastExpr{ expr };
     1107                ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
    11081108                CandidateRef choice = findUnfinishedKindExpression(
    11091109                        untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
     
    12441244        };
    12451245
    1246         void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) {
     1246        void resolve( std::list< ast::ptr< ast::Decl > >& translationUnit ) {
    12471247                ast::Pass< Resolver_new > resolver;
    12481248                accept_all( translationUnit, resolver );
     
    12781278                ast::ptr< ast::FunctionDecl > ret = functionDecl;
    12791279                for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {
    1280                         const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i];
     1280                        const ast::ptr< ast::DeclWithType > & d = functionDecl->type->params[i];
    12811281
    12821282                        if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {
     
    12951295                        }
    12961296                }
    1297                 return ret.get();
     1297                return ret.release();
    12981298        }
    12991299
     
    13181318                // in case we decide to allow nested enums
    13191319                GuardValue( inEnumDecl );
    1320                 inEnumDecl = false;
     1320                inEnumDecl = true;
    13211321        }
    13221322
  • src/ResolvExpr/SatisfyAssertions.cpp

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

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

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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    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

    r665f432 r9802f4c  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jul 19 14:39:00 2019
    13 // Update Count     : 22
     12// Last Modified On : Fri Oct  4 15:38:00 2019
     13// Update Count     : 23
    1414//
    1515
     
    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::CV::Atomic | ast::CV::Mutex };
    327327
  • src/main.cc

    r665f432 r9802f4c  
    2929#include <string>                           // for char_traits, operator<<
    3030
     31#include "AST/Convert.hpp"
    3132#include "CompilationState.h"
    3233#include "../config.h"                      // for CFA_LIBDIR
     
    303304                } // if
    304305
    305                 PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
     306                // PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
     307                {
     308                        auto transUnit = convert( move( translationUnit ) );
     309                        PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
     310                        translationUnit = convert( move( transUnit ) );
     311                }
     312
    306313                if ( exprp ) {
    307314                        dump( translationUnit );
Note: See TracChangeset for help on using the changeset viewer.