Changes in / [1fcc2f3:d056d0d]


Ignore:
Files:
1 added
6 deleted
47 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Attribute.hpp

    r1fcc2f3 rd056d0d  
    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);
    5553};
    5654
  • src/AST/CVQualifiers.hpp

    r1fcc2f3 rd056d0d  
    2727                Restrict = 1 << 1,
    2828                Volatile = 1 << 2,
    29                 Mutex    = 1 << 3,
    30                 Atomic   = 1 << 4,
    31                 NumQualifiers = 5
     29                Lvalue   = 1 << 3,
     30                Mutex    = 1 << 4,
     31                Atomic   = 1 << 5,
     32                NumQualifiers = 6
    3233        };
    3334
    3435        /// Mask for equivalence-preserving qualfiers
    35         enum { EquivQualifiers = ~Restrict };
     36        enum { EquivQualifiers = ~(Restrict | Lvalue) };
    3637
    3738        /// Underlying data for qualifiers
     
    4344                                bool is_restrict : 1;
    4445                                bool is_volatile : 1;
     46                                bool is_lvalue   : 1;
    4547                                bool is_mutex    : 1;
    4648                                bool is_atomic   : 1;
  • src/AST/Convert.cpp

    r1fcc2f3 rd056d0d  
    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                 }
    621610                return visitBaseExpr_skipResultType(src, tgt);
    622611        }
     
    21242113                                old->location,
    21252114                                GET_ACCEPT_1(member, DeclWithType),
    2126                                 GET_ACCEPT_1(aggregate, Expr),
    2127                                 ast::MemberExpr::NoOpConstructionChosen
     2115                                GET_ACCEPT_1(aggregate, Expr)
    21282116                        )
    21292117                );
  • src/AST/Decl.cpp

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

    r1fcc2f3 rd056d0d  
    3232
    3333// Must be included in *all* AST classes; should be #undef'd at the end of the file
    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);
     34#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
    3735
    3836namespace ast {
     
    8987        virtual const Type * get_type() const = 0;
    9088        /// Set type of this declaration. May be verified by subclass
    91         virtual void set_type( const Type * ) = 0;
     89        virtual void set_type(Type *) = 0;
    9290
    9391        const DeclWithType * accept( Visitor & v ) const override = 0;
     
    112110
    113111        const Type* get_type() const override { return type; }
    114         void set_type( const Type * ty ) override { type = ty; }
     112        void set_type( Type * ty ) override { type = ty; }
    115113
    116114        const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
     
    134132
    135133        const Type * get_type() const override;
    136         void set_type( const Type * t ) override;
     134        void set_type(Type * t) override;
    137135
    138136        bool has_body() const { return stmts; }
     
    151149        std::vector<ptr<DeclWithType>> assertions;
    152150
    153         NamedTypeDecl(
    154                 const CodeLocation & loc, const std::string & name, Storage::Classes storage,
    155                 const Type * b, Linkage::Spec spec = Linkage::Cforall )
     151        NamedTypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
     152                Type* b, Linkage::Spec spec = Linkage::Cforall )
    156153        : Decl( loc, name, storage, spec ), base( b ), params(), assertions() {}
    157154
     
    188185        };
    189186
    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 )
     187        TypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, Type* b,
     188                TypeVar::Kind k, bool s, Type* i = nullptr )
    193189        : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeVar::Ttype || s ),
    194190          init( i ) {}
  • src/AST/Expr.cpp

    r1fcc2f3 rd056d0d  
    1010// Created On       : Wed May 15 17:00:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Created On       : Fri Oct  4 15:34:00 2019
    13 // Update Count     : 4
     12// Created On       : Thr Jun 13 13:38:00 2019
     13// Update Count     : 2
    1414//
    1515
     
    2020#include <vector>
    2121
    22 #include "Copy.hpp"                // for shallowCopy
    23 #include "Eval.hpp"                // for call
    2422#include "GenericSubstitution.hpp"
    25 #include "LinkageSpec.hpp"
    2623#include "Stmt.hpp"
    2724#include "Type.hpp"
     
    3027#include "Common/SemanticError.h"
    3128#include "GenPoly/Lvalue.h"        // for referencesPermissable
    32 #include "InitTweak/InitTweak.h"   // for getFunction, getPointerBase
     29#include "InitTweak/InitTweak.h"   // for getPointerBase
    3330#include "ResolvExpr/typeops.h"    // for extractResultType
    3431#include "Tuples/Tuples.h"         // for makeTupleType
    3532
    3633namespace ast {
    37 
    38 namespace {
    39         std::set<std::string> const lvalueFunctionNames = {"*?", "?[?]"};
    40 }
    41 
    42 // --- Expr
    43 bool Expr::get_lvalue() const {
    44         return false;
    45 }
    4634
    4735// --- ApplicationExpr
     
    5846}
    5947
    60 bool 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 
    6748// --- UntypedExpr
    6849
     
    7051        assert( arg );
    7152
    72         UntypedExpr * ret = call( loc, "*?", arg );
     53        UntypedExpr * ret = new UntypedExpr{
     54                loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } }
     55        };
    7356        if ( const Type * ty = arg->result ) {
    7457                const Type * base = InitTweak::getPointerBase( ty );
     
    8265                        // base type
    8366                        ret->result = base;
     67                        add_qualifiers( ret->result, CV::Lvalue );
    8468                }
    8569        }
    8670        return ret;
    87 }
    88 
    89 bool UntypedExpr::get_lvalue() const {
    90         std::string fname = InitTweak::getFunctionName( this );
    91         return lvalueFunctionNames.count( fname );
    9271}
    9372
     
    9574        assert( lhs && rhs );
    9675
    97         UntypedExpr * ret = call( loc, "?=?", lhs, rhs );
     76        UntypedExpr * ret = new UntypedExpr{
     77                loc, new NameExpr{loc, "?=?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ lhs }, ptr<Expr>{ rhs } }
     78        };
    9879        if ( lhs->result && rhs->result ) {
    9980                // if both expressions are typed, assumes that this assignment is a C bitwise assignment,
     
    127108AddressExpr::AddressExpr( const CodeLocation & loc, const Expr * a ) : Expr( loc ), arg( a ) {
    128109        if ( arg->result ) {
    129                 if ( arg->get_lvalue() ) {
     110                if ( arg->result->is_lvalue() ) {
    130111                        // lvalue, retains all levels of reference, and gains a pointer inside the references
    131112                        Type * res = addrType( arg->result );
     113                        res->set_lvalue( false ); // result of & is never an lvalue
    132114                        result = res;
    133115                } else {
     
    136118                                        dynamic_cast< const ReferenceType * >( arg->result.get() ) ) {
    137119                                Type * res = addrType( refType->base );
     120                                res->set_lvalue( false ); // result of & is never an lvalue
    138121                                result = res;
    139122                        } else {
     
    155138CastExpr::CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g )
    156139: Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {}
    157 
    158 bool 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 }
    162140
    163141// --- KeywordCastExpr
     
    174152}
    175153
    176 // --- UntypedMemberExpr
    177 
    178 bool UntypedMemberExpr::get_lvalue() const {
    179         return aggregate->get_lvalue();
    180 }
    181 
    182154// --- MemberExpr
    183155
     
    188160        assert( aggregate->result );
    189161
    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 
     162        // take ownership of member type
     163        result = mem->get_type();
    227164        // substitute aggregate generic parameters into member type
    228165        genericSubstitution( aggregate->result ).apply( result );
    229         // ensure appropriate restrictions from aggregate type
    230         add_qualifiers( result, aggregate->result->qualifiers );
    231 }
    232 
    233 MemberExpr::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 
    242 bool MemberExpr::get_lvalue() const {
    243         // This is actually wrong by C, but it works with our current set-up.
    244         return true;
     166        // ensure lvalue and appropriate restrictions from aggregate type
     167        add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue );
    245168}
    246169
     
    254177        assert( var );
    255178        assert( var->get_type() );
    256         result = shallowCopy( var->get_type() );
    257 }
    258 
    259 bool VariableExpr::get_lvalue() const {
    260         // It isn't always an lvalue, but it is never an rvalue.
    261         return true;
     179        result = var->get_type();
     180        add_qualifiers( result, CV::Lvalue );
    262181}
    263182
     
    345264        const CodeLocation & loc, const Expr * a1, const Expr * a2, LogicalFlag ia )
    346265: Expr( loc, new BasicType{ BasicType::SignedInt } ), arg1( a1 ), arg2( a2 ), isAnd( ia ) {}
    347 
    348 // --- CommaExpr
    349 bool 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 }
    354266
    355267// --- ConstructorExpr
     
    371283        assert( t && i );
    372284        result = t;
    373 }
    374 
    375 bool CompoundLiteralExpr::get_lvalue() const {
    376         return true;
     285        add_qualifiers( result, CV::Lvalue );
    377286}
    378287
     
    391300        // like MemberExpr, TupleIndexExpr is always an lvalue
    392301        result = type->types[ index ];
    393 }
    394 
    395 bool TupleIndexExpr::get_lvalue() const {
    396         return tuple->get_lvalue();
     302        add_qualifiers( result, CV::Lvalue );
    397303}
    398304
  • src/AST/Expr.hpp

    r1fcc2f3 rd056d0d  
    99// Author           : Aaron B. Moss
    1010// Created On       : Fri May 10 10:30:00 2019
    11 // Last Modified By : Andrew Beach
    12 // Created On       : Thr Sep 26 12:51:00 2019
    13 // Update Count     : 2
     11// Last Modified By : Aaron B. Moss
     12// Created On       : Fri May 10 10:30:00 2019
     13// Update Count     : 1
    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 \
    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 
     32#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
    3633
    3734class ConverterOldToNew;
     
    187184
    188185        Expr * set_extension( bool ex ) { extension = ex; return this; }
    189         virtual bool get_lvalue() const;
    190186
    191187        virtual const Expr * accept( Visitor & v ) const override = 0;
     
    204200        ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} );
    205201
    206         bool get_lvalue() const final;
    207 
    208202        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    209203private:
     
    220214        UntypedExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} )
    221215        : Expr( loc ), func( f ), args( std::move(as) ) {}
    222 
    223         bool get_lvalue() const final;
    224216
    225217        /// Creates a new dereference expression
     
    298290        CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {}
    299291
    300         bool get_lvalue() const final;
    301 
    302292        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    303293private:
     
    347337        : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); }
    348338
    349         bool get_lvalue() const final;
    350 
    351339        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    352340private:
     
    363351        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg );
    364352
    365         bool get_lvalue() const final;
    366 
    367353        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    368354private:
    369355        MemberExpr * clone() const override { return new MemberExpr{ *this }; }
    370356        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;
    378357};
    379358
     
    385364        VariableExpr( const CodeLocation & loc );
    386365        VariableExpr( const CodeLocation & loc, const DeclWithType * v );
    387 
    388         bool get_lvalue() const final;
    389366
    390367        /// generates a function pointer for a given function
     
    554531
    555532        CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
    556         : Expr( loc ), arg1( a1 ), arg2( a2 ) {
    557                 this->result = a2->result;
    558         }
    559 
    560         bool get_lvalue() const final;
     533        : Expr( loc ), arg1( a1 ), arg2( a2 ) {}
    561534
    562535        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    631604        CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i );
    632605
    633         bool get_lvalue() const final;
    634 
    635606        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    636607private:
     
    688659
    689660        TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i );
    690 
    691         bool get_lvalue() const final;
    692661
    693662        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Init.hpp

    r1fcc2f3 rd056d0d  
    2525
    2626// Must be included in *all* AST classes; should be #undef'd at the end of the file
    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);
     27#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
    3028
    3129namespace ast {
  • src/AST/Node.cpp

    r1fcc2f3 rd056d0d  
    1717#include "Fwd.hpp"
    1818
    19 #include <csignal>  // MEMORY DEBUG -- for raise
    2019#include <iostream>
    2120
     
    3029#include "Print.hpp"
    3130
    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
    39 void * MEM_TRAP_OBJ = nullptr;
    40 
    41 void _trap( const void * node ) {
    42         if ( node == MEM_TRAP_OBJ ) std::raise(SIGTRAP);
    43 }
    44 
    45 template< typename node_t, enum ast::Node::ref_type ref_t >
    46 void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) {
    47         node->increment(ref_t);
    48         _trap( node );
    49 }
    50 
    51 template< typename node_t, enum ast::Node::ref_type ref_t >
    52 void 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 
    57 template< typename node_t, enum ast::Node::ref_type ref_t >
    58 void ast::ptr_base<node_t, ref_t>::_check() const {
    59         // if(node) assert(node->was_ever_strong == false || node->strong_count > 0);
    60 }
     31template< typename node_t, enum ast::Node::ref_type ref_t >
     32void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) { node->increment(ref_t); }
     33
     34template< typename node_t, enum ast::Node::ref_type ref_t >
     35void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node ) { node->decrement(ref_t); }
     36
     37template< typename node_t, enum ast::Node::ref_type ref_t >
     38void ast::ptr_base<node_t, ref_t>::_check() const { if(node) assert(node->was_ever_strong == false || node->strong_count > 0); }
    6139
    6240template< typename node_t, enum ast::Node::ref_type ref_t >
  • src/AST/Node.hpp

    r1fcc2f3 rd056d0d  
    3838        Node& operator= (const Node&) = delete;
    3939        Node& operator= (Node&&) = delete;
    40         virtual ~Node() {}
     40        virtual ~Node() = default;
    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);
    6159
    6260        mutable size_t strong_count = 0;
     
    7169        }
    7270
    73         void decrement(ast::Node::ref_type ref, bool do_delete = true) const {
     71        void decrement(ast::Node::ref_type ref) const {
    7472                switch (ref) {
    7573                        case ref_type::strong: strong_count--; break;
     
    7775                }
    7876
    79                 if( do_delete && !strong_count && !weak_count) {
     77                if(!strong_count && !weak_count) {
    8078                        delete this;
    8179                }
     
    9694        assertf(
    9795                node->weak_count == 0,
    98                 "Error: mutating node with weak references to it will invalidate some references"
     96                "Error: mutating node with weak references to it will invalided some references"
    9997        );
    10098        return node->clone();
     
    106104        // skip mutate if equivalent
    107105        if ( node->*field == val ) return node;
    108 
     106       
    109107        // mutate and return
    110108        node_t * ret = mutate( node );
     
    125123        (ret->*field)[i] = std::forward< field_t >( val );
    126124        return ret;
    127 }
    128 
    129 /// Mutate an entire indexed collection by cloning to accepted value
    130 template<typename node_t, typename parent_t, typename coll_t>
    131 const 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;
    136125}
    137126
     
    230219        operator const node_t * () const { _check(); return node; }
    231220
    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 
    241221        /// wrapper for convenient access to dynamic_cast
    242222        template<typename o_node_t>
     
    264244
    265245        void _inc( const node_t * other );
    266         void _dec( const node_t * other, bool do_delete = true );
     246        void _dec( const node_t * other );
    267247        void _check() const;
    268248
  • src/AST/Pass.hpp

    r1fcc2f3 rd056d0d  
    3535#include "AST/SymbolTable.hpp"
    3636
    37 #include "AST/ForallSubstitutionTable.hpp"
    38 
    3937// Private prelude header, needed for some of the magic tricks this class pulls off
    4038#include "AST/Pass.proto.hpp"
     
    4846//
    4947// Several additional features are available through inheritance
    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
     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
    6764//-------------------------------------------------------------------------------------------------
    6865template< typename pass_t >
     
    204201        container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
    205202
    206         /// Mutate forall-list, accounting for presence of type substitution map
    207         template<typename node_t>
    208         void mutate_forall( const node_t *& );
    209 
    210203public:
    211204        /// Logic to call the accept and mutate the parent if needed, delegates call to accept
     
    216209        /// Internal RAII guard for symbol table features
    217210        struct guard_symtab {
    218                 guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass.pass, 0); }
    219                 ~guard_symtab()                                   { __pass::symtab::leave(pass.pass, 0); }
     211                guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass, 0); }
     212                ~guard_symtab()                                   { __pass::symtab::leave(pass, 0); }
    220213                Pass<pass_t> & pass;
    221214        };
     
    223216        /// Internal RAII guard for scope features
    224217        struct guard_scope {
    225                 guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass.pass, 0); }
    226                 ~guard_scope()                                   { __pass::scope::leave(pass.pass, 0); }
     218                guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass, 0); }
     219                ~guard_scope()                                   { __pass::scope::leave(pass, 0); }
    227220                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;
    237221        };
    238222
     
    329313        SymbolTable symtab;
    330314};
    331 
    332 /// Use when the templated visitor needs to keep TypeInstType instances properly linked to TypeDecl
    333 struct WithForallSubstitutor {
    334         ForallSubstitutionTable subs;
    335 };
    336 
    337315}
    338316
  • src/AST/Pass.impl.hpp

    r1fcc2f3 rd056d0d  
    127127                        , decltype( node->accept(*this) )
    128128                >::type
     129
    129130        {
    130131                __pedantic_pass_assert( __visit_children() );
    131                 __pedantic_pass_assert( node );
     132                __pedantic_pass_assert( expr );
    132133
    133134                static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR");
     
    322323        }
    323324
    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         }
    340325}
    341326
     
    444429                        guard_symtab guard { *this };
    445430                        // implicit add __func__ identifier as specified in the C manual 6.4.2.2
    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 },
     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 ) ),
    450435                                        nullptr, VariableLen, DynamicDim
    451                                 }
    452                         } };
    453                         __pass::symtab::addId( pass, 0, func );
     436                                )
     437                        );
     438                        __pass::symtab::addId( pass, 0, &func );
    454439                        VISIT(
    455440                                maybe_accept( node, &FunctionDecl::type );
     
    625610        VISIT({
    626611                // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    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);
     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);
    631616                });
    632617                ValueGuard< bool > guard2( inFunction );
     
    953938        // For now this isn't visited, it is unclear if this causes problem
    954939        // if all tests are known to pass, remove this code
    955         VISIT(
    956                 maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
    957         )
     940        // VISIT(
     941        //      maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
     942        // )
    958943
    959944        VISIT_END( Stmt, node );
     
    16821667        VISIT_START( node );
    16831668
    1684         VISIT({
    1685                 guard_forall_subs forall_guard { *this, node };
    1686                 mutate_forall( node );
     1669        VISIT(
     1670                maybe_accept( node, &FunctionType::forall  );
    16871671                maybe_accept( node, &FunctionType::returns );
    16881672                maybe_accept( node, &FunctionType::params  );
    1689         })
     1673        )
    16901674
    16911675        VISIT_END( Type, node );
     
    17021686        VISIT({
    17031687                guard_symtab guard { *this };
    1704                 guard_forall_subs forall_guard { *this, node };
    1705                 mutate_forall( node );
     1688                maybe_accept( node, &StructInstType::forall );
    17061689                maybe_accept( node, &StructInstType::params );
    17071690        })
     
    17161699        VISIT_START( node );
    17171700
    1718         __pass::symtab::addUnion( pass, 0, node->name );
    1719 
    1720         VISIT({
     1701        __pass::symtab::addStruct( pass, 0, node->name );
     1702
     1703        {
    17211704                guard_symtab guard { *this };
    1722                 guard_forall_subs forall_guard { *this, node };
    1723                 mutate_forall( node );
     1705                maybe_accept( node, &UnionInstType::forall );
    17241706                maybe_accept( node, &UnionInstType::params );
    1725         })
     1707        }
    17261708
    17271709        VISIT_END( Type, node );
     
    17341716        VISIT_START( node );
    17351717
    1736         VISIT({
    1737                 guard_forall_subs forall_guard { *this, node };
    1738                 mutate_forall( node );
     1718        VISIT(
     1719                maybe_accept( node, &EnumInstType::forall );
    17391720                maybe_accept( node, &EnumInstType::params );
    1740         })
     1721        )
    17411722
    17421723        VISIT_END( Type, node );
     
    17491730        VISIT_START( node );
    17501731
    1751         VISIT({
    1752                 guard_forall_subs forall_guard { *this, node };
    1753                 mutate_forall( node );
     1732        VISIT(
     1733                maybe_accept( node, &TraitInstType::forall );
    17541734                maybe_accept( node, &TraitInstType::params );
    1755         })
     1735        )
    17561736
    17571737        VISIT_END( Type, node );
     
    17651745
    17661746        VISIT(
    1767                 {
    1768                         guard_forall_subs forall_guard { *this, node };
    1769                         mutate_forall( node );
    1770                         maybe_accept( node, &TypeInstType::params );
    1771                 }
    1772                 // ensure that base re-bound if doing substitution
    1773                 __pass::forall::replace( pass, 0, node );
     1747                maybe_accept( node, &TypeInstType::forall );
     1748                maybe_accept( node, &TypeInstType::params );
    17741749        )
    17751750
     
    19201895                                guard_symtab guard { *this };
    19211896                                auto new_node = p.second->accept( *this );
    1922                                 if (new_node != p.second) mutated = true;
     1897                                if (new_node != p.second) mutated = false;
    19231898                                new_map.insert({ p.first, new_node });
    19241899                        }
     
    19361911                                guard_symtab guard { *this };
    19371912                                auto new_node = p.second->accept( *this );
    1938                                 if (new_node != p.second) mutated = true;
     1913                                if (new_node != p.second) mutated = false;
    19391914                                new_map.insert({ p.first, new_node });
    19401915                        }
  • src/AST/Pass.proto.hpp

    r1fcc2f3 rd056d0d  
    263263                template<typename pass_t>
    264264                static inline void leave( pass_t &, long ) {}
    265         } // namespace scope
    266 
    267         // Certain passes desire an up to date symbol table automatically
     265        };
     266
     267        // Finally certain pass 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, void() ) {
     272                static inline auto enter( pass_t & pass, int ) -> decltype( pass.symtab.enterScope(), void() ) {
    273273                        pass.symtab.enterScope();
    274274                }
     
    278278
    279279                template<typename pass_t>
    280                 static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab, void() ) {
     280                static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab.leaveScope(), 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 Decl * );
     313                SYMTAB_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Node * );
    314314
    315315                // A few extra functions have more complicated behaviour, they are hand written
     
    356356                #undef SYMTAB_FUNC1
    357357                #undef SYMTAB_FUNC2
    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
     358        };
     359};
     360};
  • src/AST/Stmt.hpp

    r1fcc2f3 rd056d0d  
    2727
    2828// Must be included in *all* AST classes; should be #undef'd at the end of the file
    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);
     29#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
    3230
    3331namespace ast {
     
    399397class ImplicitCtorDtorStmt final : public Stmt {
    400398public:
    401         ptr<Stmt> callStmt;
     399        readonly<Stmt> callStmt;
    402400
    403401        ImplicitCtorDtorStmt( const CodeLocation & loc, const Stmt * callStmt,
  • src/AST/Type.cpp

    r1fcc2f3 rd056d0d  
    2121
    2222#include "Decl.hpp"
    23 #include "ForallSubstitutor.hpp" // for substituteForall
    2423#include "Init.hpp"
    25 #include "Common/utility.h"      // for copy, move
    2624#include "InitTweak/InitTweak.h" // for getPointerBase
    2725#include "Tuples/Tuples.h"       // for isTtype
     
    9391);
    9492
    95 // --- ParameterizedType
    96 
    97 void ParameterizedType::initWithSub(
    98         const ParameterizedType & o, Pass< ForallSubstitutor > & sub
    99 ) {
    100         forall = sub.pass( o.forall );
    101 }
    102 
    10393// --- FunctionType
    104 
    105 FunctionType::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 }
    11394
    11495namespace {
     
    126107
    127108// --- ReferenceToType
    128 
    129 void 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 
    134 ReferenceToType::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 
    141109std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const {
    142110        assertf( aggr(), "Must have aggregate to perform lookup" );
     
    151119// --- StructInstType
    152120
    153 StructInstType::StructInstType(
    154         const StructDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
    155 : ReferenceToType( b->name, q, move(as) ), base( b ) {}
     121StructInstType::StructInstType( const StructDecl * b, CV::Qualifiers q,
     122        std::vector<ptr<Attribute>>&& as )
     123: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
    156124
    157125bool StructInstType::isComplete() const { return base ? base->body : false; }
     
    159127// --- UnionInstType
    160128
    161 UnionInstType::UnionInstType(
    162         const UnionDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
    163 : ReferenceToType( b->name, q, move(as) ), base( b ) {}
     129UnionInstType::UnionInstType( const UnionDecl * b, CV::Qualifiers q,
     130        std::vector<ptr<Attribute>>&& as )
     131: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
    164132
    165133bool UnionInstType::isComplete() const { return base ? base->body : false; }
     
    167135// --- EnumInstType
    168136
    169 EnumInstType::EnumInstType(
    170         const EnumDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
    171 : ReferenceToType( b->name, q, move(as) ), base( b ) {}
     137EnumInstType::EnumInstType( const EnumDecl * b, CV::Qualifiers q,
     138        std::vector<ptr<Attribute>>&& as )
     139: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
    172140
    173141bool EnumInstType::isComplete() const { return base ? base->body : false; }
     
    175143// --- TraitInstType
    176144
    177 TraitInstType::TraitInstType(
    178         const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
    179 : ReferenceToType( b->name, q, move(as) ), base( b ) {}
     145TraitInstType::TraitInstType( const TraitDecl * b, CV::Qualifiers q,
     146        std::vector<ptr<Attribute>>&& as )
     147: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
    180148
    181149// --- TypeInstType
    182 
    183 TypeInstType::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 }
    189150
    190151void TypeInstType::set_base( const TypeDecl * b ) {
     
    198159
    199160TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q )
    200 : Type( q ), types( move(ts) ), members() {
     161: Type( q ), types( std::move(ts) ), members() {
    201162        // This constructor is awkward. `TupleType` needs to contain objects so that members can be
    202163        // named, but members without initializer nodes end up getting constructors, which breaks
  • src/AST/Type.hpp

    r1fcc2f3 rd056d0d  
    3030
    3131// Must be included in *all* AST classes; should be #undef'd at the end of the file
    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);
     32#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
    3533
    3634namespace ast {
    37 
    38 template< typename T > class Pass;
    39 
    40 struct ForallSubstitutor;
    4135
    4236class Type : public Node {
     
    5145        bool is_volatile() const { return qualifiers.is_volatile; }
    5246        bool is_restrict() const { return qualifiers.is_restrict; }
     47        bool is_lvalue() const { return qualifiers.is_lvalue; }
    5348        bool is_mutex() const { return qualifiers.is_mutex; }
    5449        bool is_atomic() const { return qualifiers.is_atomic; }
     
    5752        Type * set_volatile( bool v ) { qualifiers.is_volatile = v; return this; }
    5853        Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; }
     54        Type * set_lvalue( bool v ) { qualifiers.is_lvalue = v; return this; }
    5955        Type * set_mutex( bool v ) { qualifiers.is_mutex = v; return this; }
    6056        Type * set_atomic( bool v ) { qualifiers.is_atomic = v; return this; }
     
    168164        static const char *typeNames[];
    169165
    170         BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     166        BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 
    171167        : Type(q, std::move(as)), kind(k) {}
    172168
     
    270266/// Base type for potentially forall-qualified types
    271267class ParameterizedType : public Type {
    272 protected:
    273         /// initializes forall with substitutor
    274         void initWithSub( const ParameterizedType & o, Pass< ForallSubstitutor > & sub );
    275268public:
    276269        using ForallList = std::vector<ptr<TypeDecl>>;
     
    284277        ParameterizedType( CV::Qualifiers q, std::vector<ptr<Attribute>> && as = {} )
    285278        : 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
    293279
    294280private:
     
    316302        : ParameterizedType(q), returns(), params(), isVarArgs(va) {}
    317303
    318         FunctionType( const FunctionType & o );
    319 
    320304        /// true if either the parameters or return values contain a tttype
    321305        bool isTtype() const;
     
    331315/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
    332316class ReferenceToType : public ParameterizedType {
    333 protected:
    334         /// Initializes forall and parameters based on substitutor
    335         void initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub );
    336317public:
    337318        std::vector<ptr<Expr>> params;
     
    339320        bool hoistType = false;
    340321
    341         ReferenceToType(
    342                 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     322        ReferenceToType( const std::string& n, CV::Qualifiers q = {},
     323                std::vector<ptr<Attribute>> && as = {} )
    343324        : ParameterizedType(q, std::move(as)), params(), name(n) {}
    344 
    345         ReferenceToType( const ReferenceToType & o );
    346325
    347326        /// Gets aggregate declaration this type refers to
     
    360339        readonly<StructDecl> base;
    361340
    362         StructInstType(
    363                 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     341        StructInstType( const std::string& n, CV::Qualifiers q = {},
     342                std::vector<ptr<Attribute>> && as = {} )
    364343        : ReferenceToType( n, q, std::move(as) ), base() {}
    365 
    366         StructInstType(
    367                 const StructDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
     344        StructInstType( const StructDecl * b, CV::Qualifiers q = {},
     345                std::vector<ptr<Attribute>> && as = {} );
    368346
    369347        bool isComplete() const override;
     
    382360        readonly<UnionDecl> base;
    383361
    384         UnionInstType(
    385                 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     362        UnionInstType( const std::string& n, CV::Qualifiers q = {},
     363                std::vector<ptr<Attribute>> && as = {} )
    386364        : ReferenceToType( n, q, std::move(as) ), base() {}
    387 
    388         UnionInstType(
    389                 const UnionDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
     365        UnionInstType( const UnionDecl * b, CV::Qualifiers q = {},
     366                std::vector<ptr<Attribute>> && as = {} );
    390367
    391368        bool isComplete() const override;
     
    404381        readonly<EnumDecl> base;
    405382
    406         EnumInstType(
    407                 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     383        EnumInstType( const std::string& n, CV::Qualifiers q = {},
     384                std::vector<ptr<Attribute>> && as = {} )
    408385        : ReferenceToType( n, q, std::move(as) ), base() {}
    409 
    410         EnumInstType(
    411                 const EnumDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
     386        EnumInstType( const EnumDecl * b, CV::Qualifiers q = {},
     387                std::vector<ptr<Attribute>> && as = {} );
    412388
    413389        bool isComplete() const override;
     
    426402        readonly<TraitDecl> base;
    427403
    428         TraitInstType(
    429                 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     404        TraitInstType( const std::string& n, CV::Qualifiers q = {},
     405                std::vector<ptr<Attribute>> && as = {} )
    430406        : ReferenceToType( n, q, std::move(as) ), base() {}
    431 
    432         TraitInstType(
    433                 const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
     407        TraitInstType( const TraitDecl * b, CV::Qualifiers q = {},
     408                std::vector<ptr<Attribute>> && as = {} );
    434409
    435410        // not meaningful for TraitInstType
     
    450425        TypeVar::Kind kind;
    451426
    452         TypeInstType(
    453                 const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
     427        TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
    454428                std::vector<ptr<Attribute>> && as = {} )
    455429        : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
    456 
    457         TypeInstType(
    458                 const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {},
     430        TypeInstType( const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {},
    459431                std::vector<ptr<Attribute>> && as = {} )
    460432        : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
    461 
    462         TypeInstType( const TypeInstType & o );
    463433
    464434        /// sets `base`, updating `kind` correctly
  • src/AST/TypeEnvironment.hpp

    r1fcc2f3 rd056d0d  
    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 >
    146         auto apply( node_t && type ) const {
     145        template< typename node_t, enum Node::ref_type ref_t >
     146        int apply( ptr_base< node_t, ref_t > & type ) const {
    147147                TypeSubstitution sub;
    148148                writeToSubstitution( sub );
    149                 return sub.apply( std::forward<node_t>(type) );
    150         }
    151 
    152         template< typename node_t >
    153         auto applyFree( node_t && type ) const {
     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 {
    154154                TypeSubstitution sub;
    155155                writeToSubstitution( sub );
    156                 return sub.applyFree( std::forward<node_t>(type) );
     156                return sub.applyFree( 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

    r1fcc2f3 rd056d0d  
    9292namespace {
    9393        struct EnvTrimmer {
    94                 const TypeSubstitution * env;
     94                ptr<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
    110111                Pass<EnvTrimmer> trimmer( env, newEnv );
    111112                expr->accept( trimmer );
     113#else
     114                (void)expr;
     115                (void)env;
     116#endif
    112117                return newEnv;
    113118        }
     
    116121
    117122void TypeSubstitution::normalize() {
    118         Pass<Substituter> sub( *this, true );
     123#if TIME_TO_CONVERT_PASSES
     124        PassVisitor<Substituter> sub( *this, true );
    119125        do {
    120126                sub.pass.subCount = 0;
    121127                sub.pass.freeOnly = true;
    122128                for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
    123                         i->second = i->second->accept( sub );
     129                        i->second = i->second->acceptMutator( sub );
    124130                }
    125131        } while ( sub.pass.subCount );
    126 }
    127 
    128 const Type * TypeSubstitution::Substituter::postvisit( const TypeInstType *inst ) {
     132#endif
     133}
     134
     135#if TIME_TO_CONVERT_PASSES
     136
     137Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) {
    129138        BoundVarsType::const_iterator bound = boundVars.find( inst->name );
    130139        if ( bound != boundVars.end() ) return inst;
     
    137146                // Note: this does not prevent cycles in the general case, so it may be necessary to do something more sophisticated here.
    138147                // TODO: investigate preventing type variables from being bound to themselves in the first place.
    139                 if ( const TypeInstType * replacement = i->second.as<TypeInstType>() ) {
     148                if ( TypeInstType * replacement = i->second.as<TypeInstType>() ) {
    140149                        if ( inst->name == replacement->name ) {
    141150                                return inst;
     
    144153                // std::cerr << "found " << inst->name << ", replacing with " << i->second << std::endl;
    145154                subCount++;
    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 
    155 const Expr * TypeSubstitution::Substituter::postvisit( const NameExpr * nameExpr ) {
     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
     163Expression * TypeSubstitution::Substituter::postmutate( NameExpr * nameExpr ) {
    156164        VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name );
    157165        if ( i == sub.varEnv.end() ) {
     
    159167        } else {
    160168                subCount++;
    161                 return i->second;
    162         } // if
    163 }
    164 
    165 void TypeSubstitution::Substituter::previsit( const ParameterizedType * ptype ) {
     169                delete nameExpr;
     170                return i->second->clone();
     171        } // if
     172}
     173
     174void TypeSubstitution::Substituter::premutate( Type * type ) {
    166175        GuardValue( boundVars );
    167176        // bind type variables from forall-qualifiers
    168177        if ( freeOnly ) {
    169                 for ( const TypeDecl * tyvar : ptype->forall ) {
    170                                 boundVars.insert( tyvar->name );
     178                for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
     179                        boundVars.insert( (*tyvar)->name );
    171180                } // for
    172181        } // if
    173182}
    174183
    175 void TypeSubstitution::Substituter::handleAggregateType( const ReferenceToType * type ) {
     184template< typename TypeClass >
     185void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) {
    176186        GuardValue( boundVars );
    177187        // bind type variables from forall-qualifiers
    178188        if ( freeOnly ) {
    179                 for ( const TypeDecl * tyvar : type->forall ) {
    180                         boundVars.insert( tyvar->name );
     189                for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
     190                        boundVars.insert( (*tyvar)->name );
    181191                } // for
    182192                // bind type variables from generic type instantiations
    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 
    193 void TypeSubstitution::Substituter::previsit( const StructInstType * aggregateUseType ) {
     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
     202void TypeSubstitution::Substituter::premutate( StructInstType * aggregateUseType ) {
    194203        handleAggregateType( aggregateUseType );
    195204}
    196205
    197 void TypeSubstitution::Substituter::previsit( const UnionInstType *aggregateUseType ) {
     206void TypeSubstitution::Substituter::premutate( UnionInstType *aggregateUseType ) {
    198207        handleAggregateType( aggregateUseType );
    199208}
     209
     210#endif
    200211
    201212} // namespace ast
  • src/AST/TypeSubstitution.hpp

    r1fcc2f3 rd056d0d  
    4444        TypeSubstitution &operator=( const TypeSubstitution &other );
    4545
    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;
     46        template< typename SynTreeClass > int apply( const SynTreeClass *& input ) const;
     47        template< typename SynTreeClass > int applyFree( const SynTreeClass *& input ) const;
    5448
    5549        template< typename node_t, enum Node::ref_type ref_t >
    5650        int apply( ptr_base< node_t, ref_t > & input ) const {
    5751                const node_t * p = input.get();
    58                 auto ret = apply(p);
    59                 input = ret.node;
    60                 return ret.count;
     52                int ret = apply(p);
     53                input = p;
     54                return ret;
    6155        }
    6256
     
    6458        int applyFree( ptr_base< node_t, ref_t > & input ) const {
    6559                const node_t * p = input.get();
    66                 auto ret = applyFree(p);
    67                 input = ret.node;
    68                 return ret.count;
     60                int ret = applyFree(p);
     61                input = p;
     62                return ret;
    6963        }
    7064
     
    161155                Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
    162156
    163                 const Type * postvisit( const TypeInstType * aggregateUseType );
    164                 const Expr * postvisit( const NameExpr * nameExpr );
     157#if TIME_TO_CONVERT_PASSES
     158
     159                Type * postmutate( TypeInstType * aggregateUseType );
     160                Expression * postmutate( NameExpr * nameExpr );
    165161
    166162                /// Records type variable bindings from forall-statements
    167                 void previsit( const ParameterizedType * type );
     163                void premutate( Type * type );
    168164                /// Records type variable bindings from forall-statements and instantiations of generic types
    169                 void handleAggregateType( const ReferenceToType * type );
    170 
    171                 void previsit( const StructInstType * aggregateUseType );
    172                 void previsit( const UnionInstType * aggregateUseType );
     165                template< typename TypeClass > void handleAggregateType( TypeClass * type );
     166
     167                void premutate( StructInstType * aggregateUseType );
     168                void premutate( UnionInstType * aggregateUseType );
     169
     170#endif
    173171
    174172                const TypeSubstitution & sub;
     
    181179
    182180template< typename SynTreeClass >
    183 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::apply( const SynTreeClass * input ) const {
     181int TypeSubstitution::apply( const SynTreeClass *& input ) const {
    184182        assert( input );
    185183        Pass<Substituter> sub( *this, false );
    186184        input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
    187         return { input, sub.pass.subCount };
     185///     std::cerr << "substitution result is: ";
     186///     newType->print( std::cerr );
     187///     std::cerr << std::endl;
     188        return sub.pass.subCount;
    188189}
    189190
    190191template< typename SynTreeClass >
    191 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::applyFree( const SynTreeClass * input ) const {
     192int TypeSubstitution::applyFree( const SynTreeClass *& input ) const {
    192193        assert( input );
    193194        Pass<Substituter> sub( *this, true );
    194195        input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
    195         return { input, sub.pass.subCount };
     196///     std::cerr << "substitution result is: ";
     197///     newType->print( std::cerr );
     198///     std::cerr << std::endl;
     199        return sub.pass.subCount;
    196200}
    197201
  • src/AST/module.mk

    r1fcc2f3 rd056d0d  
    2222        AST/DeclReplacer.cpp \
    2323        AST/Expr.cpp \
    24         AST/ForallSubstitutionTable.cpp \
    2524        AST/GenericSubstitution.cpp \
    2625        AST/Init.cpp \
  • src/Common/ScopedMap.h

    r1fcc2f3 rd056d0d  
    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; }
    253251        Note& getNote( size_type i ) { return scopes[i].note; }
    254252        const Note& getNote( size_type i ) const { return scopes[i].note; }
  • src/Makefile.in

    r1fcc2f3 rd056d0d  
    169169        AST/Convert.$(OBJEXT) AST/Decl.$(OBJEXT) \
    170170        AST/DeclReplacer.$(OBJEXT) AST/Expr.$(OBJEXT) \
    171         AST/ForallSubstitutionTable.$(OBJEXT) \
    172171        AST/GenericSubstitution.$(OBJEXT) AST/Init.$(OBJEXT) \
    173172        AST/LinkageSpec.$(OBJEXT) AST/Node.$(OBJEXT) \
     
    591590        AST/DeclReplacer.cpp \
    592591        AST/Expr.cpp \
    593         AST/ForallSubstitutionTable.cpp \
    594592        AST/GenericSubstitution.cpp \
    595593        AST/Init.cpp \
     
    767765        AST/$(DEPDIR)/$(am__dirstamp)
    768766AST/Expr.$(OBJEXT): AST/$(am__dirstamp) AST/$(DEPDIR)/$(am__dirstamp)
    769 AST/ForallSubstitutionTable.$(OBJEXT): AST/$(am__dirstamp) \
    770         AST/$(DEPDIR)/$(am__dirstamp)
    771767AST/GenericSubstitution.$(OBJEXT): AST/$(am__dirstamp) \
    772768        AST/$(DEPDIR)/$(am__dirstamp)
     
    12221218@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/DeclReplacer.Po@am__quote@
    12231219@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@
    12251220@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/GenericSubstitution.Po@am__quote@
    12261221@AMDEP_TRUE@@am__include@ @am__quote@AST/$(DEPDIR)/Init.Po@am__quote@
  • src/ResolvExpr/AdjustExprType.cc

    r1fcc2f3 rd056d0d  
    100100
    101101namespace {
    102         class AdjustExprType_new final : public ast::WithShortCircuiting {
     102        struct AdjustExprType_new final : public ast::WithShortCircuiting {
     103                const ast::TypeEnvironment & tenv;
    103104                const ast::SymbolTable & symtab;
    104         public:
    105                 const ast::TypeEnvironment & tenv;
    106105
    107106                AdjustExprType_new( const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
    108                 : symtab( syms ), tenv( e ) {}
     107                : tenv( e ), symtab( syms ) {}
    109108
    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; }
     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; }
    124123
    125                 const ast::Type * postvisit( const ast::ArrayType * at ) {
     124                const ast::Type * postmutate( const ast::ArrayType * at ) {
    126125                        return new ast::PointerType{ at->base, at->qualifiers };
    127126                }
    128127
    129                 const ast::Type * postvisit( const ast::FunctionType * ft ) {
     128                const ast::Type * postmutate( const ast::FunctionType * ft ) {
    130129                        return new ast::PointerType{ ft };
    131130                }
    132131
    133                 const ast::Type * postvisit( const ast::TypeInstType * inst ) {
     132                const ast::Type * postmutate( const ast::TypeInstType * inst ) {
    134133                        // replace known function-type-variables with pointer-to-function
    135134                        if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name ) ) {
  • src/ResolvExpr/Candidate.hpp

    r1fcc2f3 rd056d0d  
    5151
    5252        Candidate( const ast::Expr * x, const ast::TypeEnvironment & e )
    53         : expr( x ), cost( Cost::zero ), cvtCost( Cost::zero ), env( e ), open(), need() {
    54                 assert(x->result);
    55         }
     53        : expr( x ), cost( Cost::zero ), cvtCost( Cost::zero ), env( e ), open(), need() {}
    5654
    5755        Candidate( const Candidate & o, const ast::Expr * x, const Cost & addedCost = Cost::zero )
    5856        : expr( x ), cost( o.cost + addedCost ), cvtCost( Cost::zero ), env( o.env ), open( o.open ),
    59           need( o.need ) {
    60                 assert(x->result);
    61         }
     57          need( o.need ) {}
    6258
    6359        Candidate(
    64                 const ast::Expr * x, const ast::TypeEnvironment & e, const ast::OpenVarSet & o,
     60                const ast::Expr * x, const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 
    6561                const ast::AssertionSet & n, const Cost & c, const Cost & cvt = Cost::zero )
    66         : expr( x ), cost( c ), cvtCost( cvt ), env( e ), open( o ), need( n.begin(), n.end() ) {
    67                 assert(x->result);
    68         }
     62        : expr( x ), cost( c ), cvtCost( cvt ), env( e ), open( o ), need( n.begin(), n.end() ) {}
    6963
    7064        Candidate(
     
    7266                ast::AssertionSet && n, const Cost & c, const Cost & cvt = Cost::zero )
    7367        : expr( x ), cost( c ), cvtCost( cvt ), env( std::move( e ) ), open( std::move( o ) ),
    74           need( n.begin(), n.end() ) {
    75                 assert(x->result);
    76         }
     68          need( n.begin(), n.end() ) {}
    7769};
    7870
  • src/ResolvExpr/CandidateFinder.cpp

    r1fcc2f3 rd056d0d  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed Jun 5 14:30:00 2019
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct  1 14:55:00 2019
    13 // Update Count     : 2
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Wed Jun 5 14:30:00 2019
     13// Update Count     : 1
    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, bool argIsLvalue,
    65         const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
     63Cost computeConversionCost( 
     64        const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab,
     65        const ast::TypeEnvironment & env
    6666) {
    6767        PRINT(
     
    7474                std::cerr << std::endl;
    7575        )
    76         Cost convCost = conversionCost( argType, paramType, argIsLvalue, symtab, env );
     76        Cost convCost = conversionCost( argType, paramType, 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(
    113                                 arg->result, paramType, arg->get_lvalue(), symtab, env );
     112                Cost convCost = computeConversionCost( arg->result, paramType, symtab, env );
    114113                outCost += convCost;
    115114
    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
     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 
    118117                // infer parameters and this does not currently work for the reason stated below
    119118                Cost tmpCost = convCost;
     
    124123                        return new ast::CastExpr{ arg, newType };
    125124
    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,
     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, 
    128127                        // once this is fixed it should be possible to resolve the cast.
    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
     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 
    131130                        // commontype(zero_t, DT*) is DT*, rather than nothing
    132131
    133132                        // CandidateFinder finder{ symtab, env };
    134133                        // finder.find( arg, ResolvMode::withAdjustment() );
    135                         // assertf( finder.candidates.size() > 0,
     134                        // assertf( finder.candidates.size() > 0, 
    136135                        //      "Somehow castable expression failed to find alternatives." );
    137                         // assertf( finder.candidates.size() == 1,
     136                        // assertf( finder.candidates.size() == 1, 
    138137                        //      "Somehow got multiple alternatives for known cast expression." );
    139138                        // return finder.candidates.front()->expr;
     
    144143
    145144        /// Computes conversion cost for a given candidate
    146         Cost computeApplicationConversionCost(
    147                 CandidateRef cand, const ast::SymbolTable & symtab
     145        Cost computeApplicationConversionCost( 
     146                CandidateRef cand, const ast::SymbolTable & symtab 
    148147        ) {
    149148                auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >();
     
    168167                                if ( function->isVarArgs ) {
    169168                                        convCost.incUnsafe();
    170                                         PRINT( std::cerr << "end of params with varargs function: inc unsafe: "
     169                                        PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 
    171170                                                << convCost << std::endl; ; )
    172171                                        // convert reference-typed expressions into value-typed expressions
    173                                         cand->expr = ast::mutate_field_index(
    174                                                 appExpr, &ast::ApplicationExpr::args, i,
     172                                        cand->expr = ast::mutate_field_index( 
     173                                                appExpr, &ast::ApplicationExpr::args, i, 
    175174                                                referenceToRvalueConversion( args[i], convCost ) );
    176175                                        continue;
     
    181180                                // Default arguments should be free - don't include conversion cost.
    182181                                // Unwrap them here because they are not relevant to the rest of the system
    183                                 cand->expr = ast::mutate_field_index(
     182                                cand->expr = ast::mutate_field_index( 
    184183                                        appExpr, &ast::ApplicationExpr::args, i, def->expr );
    185184                                ++param;
     
    189188                        // mark conversion cost and also specialization cost of param type
    190189                        const ast::Type * paramType = (*param)->get_type();
    191                         cand->expr = ast::mutate_field_index(
    192                                 appExpr, &ast::ApplicationExpr::args, i,
    193                                 computeExpressionConversionCost(
     190                        cand->expr = ast::mutate_field_index( 
     191                                appExpr, &ast::ApplicationExpr::args, i, 
     192                                computeExpressionConversionCost( 
    194193                                        args[i], paramType, symtab, cand->env, convCost ) );
    195194                        convCost.decSpec( specCost( paramType ) );
     
    199198                if ( param != params.end() ) return Cost::infinity;
    200199
    201                 // specialization cost of return types can't be accounted for directly, it disables
     200                // specialization cost of return types can't be accounted for directly, it disables 
    202201                // otherwise-identical calls, like this example based on auto-newline in the I/O lib:
    203202                //
     
    216215        }
    217216
    218         void makeUnifiableVars(
    219                 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars,
    220                 ast::AssertionSet & need
     217        void makeUnifiableVars( 
     218                const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars, 
     219                ast::AssertionSet & need 
    221220        ) {
    222221                for ( const ast::TypeDecl * tyvar : type->forall ) {
     
    255254
    256255                ArgPack()
    257                 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ),
     256                : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 
    258257                  tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    259 
     258               
     259                ArgPack(
     260                        const ast::TypeEnvironment & env, const ast::AssertionSet & need,
     261                        const ast::AssertionSet & have, const ast::OpenVarSet & open )
     262                : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ),
     263                  open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
     264               
    260265                ArgPack(
    261                         const ast::TypeEnvironment & env, const ast::AssertionSet & need,
    262                         const ast::AssertionSet & have, const ast::OpenVarSet & open )
    263                 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ),
    264                   open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    265 
    266                 ArgPack(
    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,
     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,
    270269                        unsigned nextExpl = 0, unsigned explAlt = 0 )
    271270                : parent(parent), expr( expr ), cost( cost ), env( move( env ) ), need( move( need ) ),
    272271                  have( move( have ) ), open( move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ),
    273272                  nextExpl( nextExpl ), explAlt( explAlt ) {}
    274 
     273               
    275274                ArgPack(
    276                         const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need,
     275                        const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 
    277276                        ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added )
    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 ),
     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 ), 
    280279                  tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {}
    281 
     280               
    282281                /// true if this pack is in the middle of an exploded argument
    283282                bool hasExpl() const { return nextExpl > 0; }
     
    287286                        return args[ nextArg-1 ][ explAlt ];
    288287                }
    289 
     288               
    290289                /// Ends a tuple expression, consolidating the appropriate args
    291290                void endTuple( const std::vector< ArgPack > & packs ) {
     
    308307
    309308        /// Instantiates an argument to match a parameter, returns false if no matching results left
    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
     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 
    314313        ) {
    315314                if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) {
     
    319318                                // xxx - dropping initializer changes behaviour from previous, but seems correct
    320319                                // ^^^ need to handle the case where a tuple has a default argument
    321                                 if ( ! instantiateArgument(
     320                                if ( ! instantiateArgument( 
    322321                                        type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;
    323322                                nTuples = 0;
     
    330329                } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) {
    331330                        // paramType is a ttype, consumes all remaining arguments
    332 
     331                       
    333332                        // completed tuples; will be spliced to end of results to finish
    334333                        std::vector< ArgPack > finalResults{};
     
    343342                                for ( std::size_t i = genStart; i < genEnd; ++i ) {
    344343                                        unsigned nextArg = results[i].nextArg;
    345 
     344                                       
    346345                                        // use next element of exploded tuple if present
    347346                                        if ( results[i].hasExpl() ) {
     
    353352                                                results.emplace_back(
    354353                                                        i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),
    355                                                         copy( results[i].need ), copy( results[i].have ),
     354                                                        copy( results[i].need ), copy( results[i].have ), 
    356355                                                        copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl,
    357356                                                        results[i].explAlt );
     
    371370                                                        // push empty tuple expression
    372371                                                        newResult.parent = i;
    373                                                         newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} };
     372                                                        std::vector< ast::ptr< ast::Expr > > emptyList;
     373                                                        newResult.expr =
     374                                                                new ast::TupleExpr{ CodeLocation{}, move( emptyList ) };
    374375                                                        argType = newResult.expr->result;
    375376                                                } else {
     
    399400
    400401                                                // check unification for ttype before adding to final
    401                                                 if (
    402                                                         unify(
     402                                                if ( 
     403                                                        unify( 
    403404                                                                ttype, argType, newResult.env, newResult.need, newResult.have,
    404                                                                 newResult.open, symtab )
     405                                                                newResult.open, symtab ) 
    405406                                                ) {
    406407                                                        finalResults.emplace_back( move( newResult ) );
     
    423424                                                if ( expl.exprs.empty() ) {
    424425                                                        results.emplace_back(
    425                                                                 results[i], move( env ), copy( results[i].need ),
     426                                                                results[i], move( env ), copy( results[i].need ), 
    426427                                                                copy( results[i].have ), move( open ), nextArg + 1, expl.cost );
    427 
     428                                                       
    428429                                                        continue;
    429430                                                }
     
    431432                                                // add new result
    432433                                                results.emplace_back(
    433                                                         i, expl.exprs.front(), move( env ), copy( results[i].need ),
    434                                                         copy( results[i].have ), move( open ), nextArg + 1, nTuples,
     434                                                        i, expl.exprs.front(), move( env ), copy( results[i].need ), 
     435                                                        copy( results[i].have ), move( open ), nextArg + 1, nTuples, 
    435436                                                        expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    436437                                        }
     
    478479
    479480                                        results.emplace_back(
    480                                                 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg,
     481                                                i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 
    481482                                                nTuples, Cost::zero, nextExpl, results[i].explAlt );
    482483                                }
     
    494495                                        if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {
    495496                                                results.emplace_back(
    496                                                         i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ),
     497                                                        i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 
    497498                                                        move( need ), move( have ), move( open ), nextArg, nTuples );
    498499                                        }
     
    516517                                if ( expl.exprs.empty() ) {
    517518                                        results.emplace_back(
    518                                                 results[i], move( env ), move( need ), move( have ), move( open ),
     519                                                results[i], move( env ), move( need ), move( have ), move( open ), 
    519520                                                nextArg + 1, expl.cost );
    520 
     521                                       
    521522                                        continue;
    522523                                }
     
    538539                                        // add new result
    539540                                        results.emplace_back(
    540                                                 i, expr, move( env ), move( need ), move( have ), move( open ),
     541                                                i, expr, move( env ), move( need ), move( have ), move( open ), 
    541542                                                nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    542543                                }
     
    547548                genStart = genEnd;
    548549
    549                 return genEnd != results.size();  // were any new results added?
     550                return genEnd != results.size();
    550551        }
    551552
    552553        /// Generate a cast expression from `arg` to `toType`
    553         const ast::Expr * restructureCast(
     554        const ast::Expr * restructureCast( 
    554555                ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast
    555556        ) {
    556                 if (
    557                         arg->result->size() > 1
    558                         && ! toType->isVoid()
    559                         && ! dynamic_cast< const ast::ReferenceType * >( toType )
     557                if ( 
     558                        arg->result->size() > 1 
     559                        && ! toType->isVoid() 
     560                        && ! dynamic_cast< const ast::ReferenceType * >( toType ) 
    560561                ) {
    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
     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 
    565566                        // UniqueExpr ensures that the side effects will still be produced)
    566567                        if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {
    567                                 // expressions which may contain side effects require a single unique instance of
     568                                // expressions which may contain side effects require a single unique instance of 
    568569                                // the expression
    569570                                arg = new ast::UniqueExpr{ arg->location, arg };
     
    573574                                // cast each component
    574575                                ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i };
    575                                 components.emplace_back(
     576                                components.emplace_back( 
    576577                                        restructureCast( idx, toType->getComponent( i ), isGenerated ) );
    577578                        }
     
    593594
    594595        /// Actually visits expressions to find their candidate interpretations
    595         class Finder final : public ast::WithShortCircuiting {
     596        struct Finder final : public ast::WithShortCircuiting {
     597                CandidateFinder & selfFinder;
    596598                const ast::SymbolTable & symtab;
    597         public:
    598                 CandidateFinder & selfFinder;
    599599                CandidateList & candidates;
    600600                const ast::TypeEnvironment & tenv;
     
    602602
    603603                Finder( CandidateFinder & f )
    604                 : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
     604                : selfFinder( f ), symtab( f.symtab ), 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
    679                         // parameter list are still considered open
     678                        // add all type variables as open variables now so that those not used in the parameter
     679                        // 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->get_lvalue() || x->result.as< ast::ReferenceType >() );
     985                        return x->result && ( x->result->is_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, cand->expr->get_lvalue(),
    1028                                                 symtab, cand->env );
     1027                                Cost thisCost = castCost( cand->expr->result, toType, symtab, cand->env );
    10291028                                PRINT(
    10301029                                        std::cerr << "working on cast with result: " << toType << std::endl;
     
    10381037                                        // count one safe conversion for each value that is thrown away
    10391038                                        thisCost.incSafe( discardedValues );
    1040                                         CandidateRef newCand = std::make_shared<Candidate>(
    1041                                                 restructureCast( cand->expr, toType, castExpr->isGenerated ),
    1042                                                 copy( cand->env ), move( open ), move( need ), cand->cost,
     1039                                        CandidateRef newCand = std::make_shared<Candidate>( 
     1040                                                restructureCast( cand->expr, toType, castExpr->isGenerated ), 
     1041                                                copy( cand->env ), move( open ), move( need ), cand->cost, 
    10431042                                                cand->cost + thisCost );
    10441043                                        inferParameters( newCand, matches );
     
    10581057                        finder.find( castExpr->arg, ResolvMode::withoutPrune() );
    10591058                        for ( CandidateRef & r : finder.candidates ) {
    1060                                 addCandidate(
    1061                                         *r,
     1059                                addCandidate( 
     1060                                        *r, 
    10621061                                        new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
    10631062                        }
     
    10681067                        aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    10691068                        for ( CandidateRef & agg : aggFinder.candidates ) {
    1070                                 // it's okay for the aggregate expression to have reference type -- cast it to the
     1069                                // it's okay for the aggregate expression to have reference type -- cast it to the 
    10711070                                // base type to treat the aggregate as the referenced value
    10721071                                Cost addedCost = Cost::zero;
     
    10751074                                // find member of the given type
    10761075                                if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {
    1077                                         addAggMembers(
     1076                                        addAggMembers( 
    10781077                                                structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10791078                                } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {
    1080                                         addAggMembers(
     1079                                        addAggMembers( 
    10811080                                                unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10821081                                } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {
     
    10981097
    10991098                                CandidateRef newCand = std::make_shared<Candidate>(
    1100                                         newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
     1099                                        newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 
    11011100                                        cost );
    11021101                                PRINT(
     
    11081107                                        std::cerr << std::endl;
    11091108                                )
    1110                                 newCand->expr = ast::mutate_field(
    1111                                         newCand->expr.get(), &ast::Expr::result,
     1109                                newCand->expr = ast::mutate_field( 
     1110                                        newCand->expr.get(), &ast::Expr::result, 
    11121111                                        renameTyVars( newCand->expr->result ) );
    1113                                 // add anonymous member interpretations whenever an aggregate value type is seen
     1112                                // add anonymous member interpretations whenever an aggregate value type is seen 
    11141113                                // as a name expression
    11151114                                addAnonConversions( newCand );
     
    11211120                        // not sufficient to just pass `variableExpr` here, type might have changed since
    11221121                        // creation
    1123                         addCandidate(
     1122                        addCandidate( 
    11241123                                new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
    11251124                }
     
    11311130                void postvisit( const ast::SizeofExpr * sizeofExpr ) {
    11321131                        if ( sizeofExpr->type ) {
    1133                                 addCandidate(
    1134                                         new ast::SizeofExpr{
    1135                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
     1132                                addCandidate( 
     1133                                        new ast::SizeofExpr{ 
     1134                                                sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 
    11361135                                        tenv );
    11371136                        } else {
     
    11421141                                CandidateList winners = findMinCost( finder.candidates );
    11431142                                if ( winners.size() != 1 ) {
    1144                                         SemanticError(
     1143                                        SemanticError( 
    11451144                                                sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );
    11461145                                }
     
    11551154                void postvisit( const ast::AlignofExpr * alignofExpr ) {
    11561155                        if ( alignofExpr->type ) {
    1157                                 addCandidate(
    1158                                         new ast::AlignofExpr{
    1159                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
     1156                                addCandidate( 
     1157                                        new ast::AlignofExpr{ 
     1158                                                alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 
    11601159                                        tenv );
    11611160                        } else {
     
    11661165                                CandidateList winners = findMinCost( finder.candidates );
    11671166                                if ( winners.size() != 1 ) {
    1168                                         SemanticError(
     1167                                        SemanticError( 
    11691168                                                alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );
    11701169                                }
     
    11731172                                choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    11741173                                choice->cost = Cost::zero;
    1175                                 addCandidate(
     1174                                addCandidate( 
    11761175                                        *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );
    11771176                        }
     
    11861185                        for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {
    11871186                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );
    1188                                 addCandidate(
     1187                                addCandidate( 
    11891188                                        new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );
    11901189                        }
     
    12191218
    12201219                                        addCandidate(
    1221                                                 new ast::LogicalExpr{
     1220                                                new ast::LogicalExpr{ 
    12221221                                                        logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
    12231222                                                move( env ), move( open ), move( need ), r1->cost + r2->cost );
     
    12571256                                                ast::AssertionSet have;
    12581257
    1259                                                 // unify true and false results, then infer parameters to produce new
     1258                                                // unify true and false results, then infer parameters to produce new 
    12601259                                                // candidates
    12611260                                                ast::ptr< ast::Type > common;
    1262                                                 if (
    1263                                                         unify(
    1264                                                                 r2->expr->result, r3->expr->result, env, need, have, open, symtab,
    1265                                                                 common )
     1261                                                if ( 
     1262                                                        unify( 
     1263                                                                r2->expr->result, r3->expr->result, env, need, have, open, symtab, 
     1264                                                                common ) 
    12661265                                                ) {
    12671266                                                        // generate typed expression
    1268                                                         ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{
     1267                                                        ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 
    12691268                                                                conditionalExpr->location, r1->expr, r2->expr, r3->expr };
    12701269                                                        newExpr->result = common ? common : r2->expr->result;
    12711270                                                        // convert both options to result type
    12721271                                                        Cost cost = r1->cost + r2->cost + r3->cost;
    1273                                                         newExpr->arg2 = computeExpressionConversionCost(
     1272                                                        newExpr->arg2 = computeExpressionConversionCost( 
    12741273                                                                newExpr->arg2, newExpr->result, symtab, env, cost );
    12751274                                                        newExpr->arg3 = computeExpressionConversionCost(
     
    12881287                        ast::TypeEnvironment env{ tenv };
    12891288                        ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
    1290 
     1289                       
    12911290                        CandidateFinder finder2{ symtab, env };
    12921291                        finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
     
    13311330
    13321331                                        ast::ptr< ast::Type > common;
    1333                                         if (
    1334                                                 unify(
    1335                                                         r1->expr->result, r2->expr->result, env, need, have, open, symtab,
    1336                                                         common )
     1332                                        if ( 
     1333                                                unify( 
     1334                                                        r1->expr->result, r2->expr->result, env, need, have, open, symtab, 
     1335                                                        common ) 
    13371336                                        ) {
    13381337                                                // generate new expression
    1339                                                 ast::RangeExpr * newExpr =
     1338                                                ast::RangeExpr * newExpr = 
    13401339                                                        new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
    13411340                                                newExpr->result = common ? common : r1->expr->result;
    13421341                                                // add candidate
    13431342                                                CandidateRef newCand = std::make_shared<Candidate>(
    1344                                                         newExpr, move( env ), move( open ), move( need ),
     1343                                                        newExpr, move( env ), move( open ), move( need ), 
    13451344                                                        r1->cost + r2->cost );
    13461345                                                inferParameters( newCand, candidates );
     
    13511350
    13521351                void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
    1353                         std::vector< CandidateFinder > subCandidates =
     1352                        std::vector< CandidateFinder > subCandidates = 
    13541353                                selfFinder.findSubExprs( tupleExpr->exprs );
    13551354                        std::vector< CandidateList > possibilities;
     
    13711370
    13721371                                addCandidate(
    1373                                         new ast::TupleExpr{ tupleExpr->location, move( exprs ) },
     1372                                        new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 
    13741373                                        move( env ), move( open ), move( need ), sumCost( subs ) );
    13751374                        }
     
    14131412                                toType = SymTab::validateType( initExpr->location, toType, symtab );
    14141413                                toType = adjustExprType( toType, tenv, symtab );
    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.
     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. 
    14181417                                CandidateFinder finder{ symtab, tenv, toType };
    14191418                                finder.find( initExpr->expr, ResolvMode::withAdjustment() );
     
    14271426                                        )
    14281427
    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
     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 
    14321431                                        // if it has fewer results than there are types to cast to.
    14331432                                        int discardedValues = cand->expr->result->size() - toType->size();
     
    14361435                                        // unification run for side-effects
    14371436                                        unify( toType, cand->expr->result, env, need, have, open, symtab );
    1438                                         Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
    1439                                                         symtab, env );
    1440 
     1437                                        Cost thisCost = castCost( cand->expr->result, toType, symtab, env );
     1438                                       
    14411439                                        if ( thisCost != Cost::infinity ) {
    14421440                                                // count one safe conversion for each value that is thrown away
    14431441                                                thisCost.incSafe( discardedValues );
    1444                                                 CandidateRef newCand = std::make_shared<Candidate>(
    1445                                                         new ast::InitExpr{
    1446                                                                 initExpr->location, restructureCast( cand->expr, toType ),
    1447                                                                 initAlt.designation },
     1442                                                CandidateRef newCand = std::make_shared<Candidate>( 
     1443                                                        new ast::InitExpr{ 
     1444                                                                initExpr->location, restructureCast( cand->expr, toType ), 
     1445                                                                initAlt.designation }, 
    14481446                                                        copy( cand->env ), move( open ), move( need ), cand->cost, thisCost );
    14491447                                                inferParameters( newCand, matches );
     
    14711469        };
    14721470
    1473         /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
     1471        /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 
    14741472        /// return type. Skips ambiguous candidates.
    14751473        CandidateList pruneCandidates( CandidateList & candidates ) {
     
    14881486                        {
    14891487                                ast::ptr< ast::Type > newType = candidate->expr->result;
    1490                                 assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());
    14911488                                candidate->env.apply( newType );
    14921489                                mangleName = Mangle::mangle( newType );
     
    14971494                                if ( candidate->cost < found->second.candidate->cost ) {
    14981495                                        PRINT(
    1499                                                 std::cerr << "cost " << candidate->cost << " beats "
     1496                                                std::cerr << "cost " << candidate->cost << " beats " 
    15001497                                                        << found->second.candidate->cost << std::endl;
    15011498                                        )
     
    15031500                                        found->second = PruneStruct{ candidate };
    15041501                                } else if ( candidate->cost == found->second.candidate->cost ) {
    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
     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 
    15071504                                        // that is at least as good
    15081505                                        if ( findDeletedExpr( candidate->expr ) ) {
     
    15181515                                } else {
    15191516                                        PRINT(
    1520                                                 std::cerr << "cost " << candidate->cost << " loses to "
     1517                                                std::cerr << "cost " << candidate->cost << " loses to " 
    15211518                                                        << found->second.candidate->cost << std::endl;
    15221519                                        )
     
    15331530
    15341531                        CandidateRef cand = target.second.candidate;
    1535 
     1532                       
    15361533                        ast::ptr< ast::Type > newResult = cand->expr->result;
    15371534                        cand->env.applyFree( newResult );
    15381535                        cand->expr = ast::mutate_field(
    15391536                                cand->expr.get(), &ast::Expr::result, move( newResult ) );
    1540 
     1537                       
    15411538                        out.emplace_back( cand );
    15421539                }
     
    15611558                std::vector< std::string > errors;
    15621559                for ( CandidateRef & candidate : candidates ) {
    1563                         satisfyAssertions( candidate, localSyms, satisfied, errors );
     1560                        satisfyAssertions( candidate, symtab, satisfied, errors );
    15641561                }
    15651562
     
    15861583
    15871584                CandidateList pruned = pruneCandidates( candidates );
    1588 
     1585               
    15891586                if ( mode.failFast && pruned.empty() ) {
    15901587                        std::ostringstream stream;
     
    16051602                )
    16061603                PRINT(
    1607                         std::cerr << "there are " << candidates.size() << " alternatives after elimination"
     1604                        std::cerr << "there are " << candidates.size() << " alternatives after elimination" 
    16081605                                << std::endl;
    16091606                )
    16101607        }
    16111608
    1612         // adjust types after pruning so that types substituted by pruneAlternatives are correctly
     1609        // adjust types after pruning so that types substituted by pruneAlternatives are correctly 
    16131610        // adjusted
    16141611        if ( mode.adjust ) {
    16151612                for ( CandidateRef & r : candidates ) {
    1616                         r->expr = ast::mutate_field(
    1617                                 r->expr.get(), &ast::Expr::result,
    1618                                 adjustExprType( r->expr->result, r->env, localSyms ) );
     1613                        r->expr = ast::mutate_field( 
     1614                                r->expr.get(), &ast::Expr::result, 
     1615                                adjustExprType( r->expr->result, r->env, symtab ) );
    16191616                }
    16201617        }
     
    16281625}
    16291626
    1630 std::vector< CandidateFinder > CandidateFinder::findSubExprs(
    1631         const std::vector< ast::ptr< ast::Expr > > & xs
     1627std::vector< CandidateFinder > CandidateFinder::findSubExprs( 
     1628        const std::vector< ast::ptr< ast::Expr > > & xs 
    16321629) {
    16331630        std::vector< CandidateFinder > out;
    16341631
    16351632        for ( const auto & x : xs ) {
    1636                 out.emplace_back( localSyms, env );
     1633                out.emplace_back( symtab, env );
    16371634                out.back().find( x, ResolvMode::withAdjustment() );
    1638 
     1635               
    16391636                PRINT(
    16401637                        std::cerr << "findSubExprs" << std::endl;
  • src/ResolvExpr/CandidateFinder.hpp

    r1fcc2f3 rd056d0d  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed Jun 5 14:30:00 2019
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct  1  9:51:00 2019
    13 // Update Count     : 2
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Wed Jun 5 14:30:00 2019
     13// Update Count     : 1
    1414//
    1515
     
    2828struct CandidateFinder {
    2929        CandidateList candidates;          ///< List of candidate resolutions
    30         const ast::SymbolTable & localSyms;   ///< Symbol table to lookup candidates
     30        const ast::SymbolTable & symtab;   ///< 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 & syms, const ast::TypeEnvironment & env,
     34        CandidateFinder( 
     35                const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
    3636                const ast::Type * tt = nullptr )
    37         : candidates(), localSyms( syms ), env( env ), targetType( tt ) {}
     37        : candidates(), symtab( symtab ), 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, bool argIsLvalue,
    59         const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
     57Cost computeConversionCost( 
     58        const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab,
     59        const ast::TypeEnvironment & env );
    6060
    6161} // namespace ResolvExpr
  • src/ResolvExpr/CastCost.cc

    r1fcc2f3 rd056d0d  
    1010// Created On       : Sun May 17 06:57:43 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct  4 15:00:00 2019
    13 // Update Count     : 9
     12// Last Modified On : Thu Aug  8 16:12:00 2019
     13// Update Count     : 8
    1414//
    1515
     
    142142
    143143                CastCost_new(
    144                         const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab,
     144                        const ast::Type * dst, const ast::SymbolTable & symtab,
    145145                        const ast::TypeEnvironment & env, CostCalculation costFunc )
    146                 : ConversionCost_new( dst, srcIsLvalue, symtab, env, costFunc ) {}
     146                : ConversionCost_new( dst, symtab, env, costFunc ) {}
    147147
    148148                void postvisit( const ast::BasicType * basicType ) {
     
    152152                                cost = Cost::unsafe;
    153153                        } else {
    154                                 cost = conversionCost( basicType, dst, srcIsLvalue, symtab, env );
     154                                cost = conversionCost( basicType, dst, 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 ); }
    195185} // anonymous namespace
    196186
    197 
    198 
    199187Cost castCost(
    200         const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
    201         const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
     188        const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
     189        const ast::TypeEnvironment & env
    202190) {
    203191        if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
     
    205193                        // check cast cost against bound type, if present
    206194                        if ( eqvClass->bound ) {
    207                                 return castCost( src, eqvClass->bound, srcIsLvalue, symtab, env );
     195                                return castCost( src, eqvClass->bound, symtab, env );
    208196                        } else {
    209197                                return Cost::infinity;
     
    213201                        auto type = strict_dynamic_cast< const ast::TypeDecl * >( named );
    214202                        if ( type->base ) {
    215                                 return castCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe;
     203                                return castCost( src, type->base, symtab, env ) + Cost::safe;
    216204                        }
    217205                }
     
    236224                #warning cast on ptrsCastable artifact of having two functions, remove when port done
    237225                return convertToReferenceCost(
    238                         src, refType, srcIsLvalue, symtab, env, localPtrsCastable );
     226                        src, refType, symtab, env,
     227                        ( int (*)(
     228                                const ast::Type *, const ast::Type *, const ast::SymbolTable &,
     229                                const ast::TypeEnvironment & )
     230                        ) ptrsCastable );
    239231        } else {
    240232                #warning cast on castCost artifact of having two functions, remove when port done
    241                 ast::Pass< CastCost_new > converter(
    242                         dst, srcIsLvalue, symtab, env, localCastCost );
     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 };
    243239                src->accept( converter );
    244240                return converter.pass.cost;
  • src/ResolvExpr/CommonType.cc

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

    r1fcc2f3 rd056d0d  
    1010// Created On       : Sun May 17 07:06:19 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Oct  4 14:45:00 2019
    13 // Update Count     : 28
     12// Last Modified On : Mon Aug 12 10:21:00 2019
     13// Update Count     : 27
    1414//
    1515
     
    497497        }
    498498
    499 namespace {
    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 }
     499static 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.
     506static 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 ); }
    510510
    511511Cost conversionCost(
    512         const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
    513         const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
     512        const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
     513        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, srcIsLvalue, symtab, env );
     518                                return conversionCost(src, eqv->bound, symtab, env );
    519519                        } else {
    520520                                return Cost::infinity;
     
    524524                        assertf( type, "Unexpected typedef." );
    525525                        if ( type->base ) {
    526                                 return conversionCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe;
     526                                return conversionCost( src, type->base, 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, srcIsLvalue, symtab, env, localPtrsAssignable );
     536                return convertToReferenceCost( src, refType, symtab, env, localPtrsAssignable );
    537537        } else {
    538                 ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
     538                ast::Pass<ConversionCost_new> converter( dst, 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, bool srcIsLvalue,
     544static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst,
    545545                int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
    546                 PtrsCalculation func ) {
     546                NumCostCalculation func ) {
    547547        if ( 0 < diff ) {
    548548                Cost cost = convertToReferenceCost(
    549                         strict_dynamic_cast< const ast::ReferenceType * >( src )->base, dst,
    550                         srcIsLvalue, (diff - 1), symtab, env, func );
     549                        strict_dynamic_cast< const ast::ReferenceType * >( src )->base,
     550                        dst, (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                         srcIsLvalue, (diff + 1), symtab, env, func );
     556                        (diff + 1), symtab, env, func );
    557557                cost.incReference();
    558558                return cost;
     
    579579                        }
    580580                } else {
    581                         ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
     581                        ast::Pass<ConversionCost_new> converter( dst, 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 ( srcIsLvalue ) {
     590                        if ( src->is_lvalue() ) {
    591591                                if ( src->qualifiers == dstAsRef->base->qualifiers ) {
    592592                                        return Cost::reference;
     
    607607
    608608Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst,
    609                 bool srcIsLvalue, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
    610                 PtrsCalculation func ) {
     609            const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
     610                NumCostCalculation func ) {
    611611        int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth();
    612         return convertToReferenceCost( src, dst, srcIsLvalue, sdepth - ddepth, symtab, env, func );
     612        return convertToReferenceCost( src, dst, sdepth - ddepth, symtab, env, func );
    613613}
    614614
     
    667667        assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
    668668
    669         cost = costCalc( refType->base, dst, srcIsLvalue, symtab, env );
     669        cost = costCalc( refType->base, dst, 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 ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
    704         cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
     703        static const ast::BasicType integer( ast::BasicType::SignedInt );
     704        cost = costCalc( &integer, dst, 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, srcIsLvalue, symtab, env );
     716                cost = costCalc( eqv->bound, dst, 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, srcIsLvalue, symtab, env ) + Cost::safe;
     726                        cost = costCalc( type->base, dst, symtab, env ) + Cost::safe;
    727727                }
    728728        }
     
    737737                auto dstEnd = dstAsTuple->types.end();
    738738                while ( srcIt != srcEnd && dstIt != dstEnd ) {
    739                         Cost newCost = costCalc( * srcIt++, * dstIt++, srcIsLvalue, symtab, env );
     739                        Cost newCost = costCalc( * srcIt++, * dstIt++, 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 );
    778774        }
    779775}
     
    793789                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    794790                }
     791        } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
     792                cost = Cost::zero;
     793                cost.incSafe( maxIntCost + 2 );
    795794        }
    796795}
  • src/ResolvExpr/ConversionCost.h

    r1fcc2f3 rd056d0d  
    1010// Created On       : Sun May 17 09:37:28 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct  4 14:59:00 2019
    13 // Update Count     : 7
     12// Last Modified On : Thu Aug  8 16:13:00 2019
     13// Update Count     : 6
    1414//
    1515
     
    7474
    7575// Some function pointer types, differ in return type.
    76 using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *, bool,
     76using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *,
    7777        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
    78 using PtrsCalculation = std::function<int(const ast::Type *, const ast::Type *,
     78using NumCostCalculation = 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;
    8685        const ast::SymbolTable & symtab;
    8786        const ast::TypeEnvironment & env;
     
    9089        Cost cost;
    9190
    92         ConversionCost_new( const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab,
     91        ConversionCost_new( const ast::Type * dst, const ast::SymbolTable & symtab,
    9392                        const ast::TypeEnvironment & env, CostCalculation costCalc ) :
    94                 dst( dst ), srcIsLvalue( srcIsLvalue ), symtab( symtab ), env( env ),
    95                 costCalc( costCalc ), cost( Cost::infinity )
     93                dst( dst ), symtab( symtab ), env( env ), costCalc( costCalc ), cost( Cost::infinity )
    9694        {}
    9795
     
    116114
    117115Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,
    118         bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env,
    119         PtrsCalculation func );
     116        const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, NumCostCalculation func );
    120117
    121118} // namespace ResolvExpr
  • src/ResolvExpr/CurrentObject.cc

    r1fcc2f3 rd056d0d  
    2121#include <string>                      // for string, operator<<, allocator
    2222
    23 #include "AST/Copy.hpp"                // for shallowCopy
    2423#include "AST/Expr.hpp"                // for InitAlternative
    2524#include "AST/GenericSubstitution.hpp" // for genericSubstitution
    2625#include "AST/Init.hpp"                // for Designation
    2726#include "AST/Node.hpp"                // for readonly
    28 #include "AST/Print.hpp"                // for readonly
    2927#include "AST/Type.hpp"
    3028#include "Common/Indenter.h"           // for Indenter, operator<<
     
    598596                SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
    599597
    600                 void setPosition(
    601                         std::deque< ptr< Expr > >::const_iterator begin,
     598                void setPosition( 
     599                        std::deque< ptr< Expr > >::const_iterator begin, 
    602600                        std::deque< ptr< Expr > >::const_iterator end
    603601                ) override {
     
    639637                        auto res = eval(expr);
    640638                        if ( ! res.second ) {
    641                                 SemanticError( location,
     639                                SemanticError( location, 
    642640                                        toString("Array designator must be a constant expression: ", expr ) );
    643641                        }
     
    646644
    647645        public:
    648                 ArrayIterator( const CodeLocation & loc, const ArrayType * at )
     646                ArrayIterator( const CodeLocation & loc, const ArrayType * at ) 
    649647                : location( loc ), array( at ), base( at->base ) {
    650648                        PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
     
    657655
    658656                void setPosition( const Expr * expr ) {
    659                         // need to permit integer-constant-expressions, including: integer constants,
    660                         // enumeration constants, character constants, sizeof expressions, alignof expressions,
     657                        // need to permit integer-constant-expressions, including: integer constants, 
     658                        // enumeration constants, character constants, sizeof expressions, alignof expressions, 
    661659                        // cast expressions
    662660                        if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) {
     
    664662                                        index = constExpr->intValue();
    665663                                } catch ( SemanticErrorException & ) {
    666                                         SemanticError( expr,
     664                                        SemanticError( expr, 
    667665                                                "Constant expression of non-integral type in array designator: " );
    668666                                }
    669667                        } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) {
    670668                                setPosition( castExpr->arg );
    671                         } else if (
    672                                 dynamic_cast< const SizeofExpr * >( expr )
    673                                 || dynamic_cast< const AlignofExpr * >( expr )
     669                        } else if ( 
     670                                dynamic_cast< const SizeofExpr * >( expr ) 
     671                                || dynamic_cast< const AlignofExpr * >( expr ) 
    674672                        ) {
    675673                                index = 0;
    676674                        } else {
    677                                 assertf( false,
     675                                assertf( false, 
    678676                                        "bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
    679677                        }
    680678                }
    681679
    682                 void setPosition(
    683                         std::deque< ptr< Expr > >::const_iterator begin,
     680                void setPosition( 
     681                        std::deque< ptr< Expr > >::const_iterator begin, 
    684682                        std::deque< ptr< Expr > >::const_iterator end
    685683                ) override {
     
    760758                }
    761759
    762                 AggregateIterator(
    763                         const CodeLocation & loc, const std::string k, const std::string & n, const Type * i,
     760                AggregateIterator( 
     761                        const CodeLocation & loc, const std::string k, const std::string & n, const Type * i, 
    764762                        const MemberList & ms )
    765                 : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ),
     763                : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ), 
    766764                  sub( genericSubstitution( i ) ) {
    767765                        PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
     
    770768
    771769        public:
    772                 void setPosition(
    773                         std::deque< ptr< Expr > >::const_iterator begin,
     770                void setPosition( 
     771                        std::deque< ptr< Expr > >::const_iterator begin, 
    774772                        std::deque< ptr< Expr > >::const_iterator end
    775773                ) final {
     
    788786                                        return;
    789787                                }
    790                                 assertf( false,
     788                                assertf( false, 
    791789                                        "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
    792790                        } else {
    793                                 assertf( false,
     791                                assertf( false, 
    794792                                        "bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() );
    795793                        }
     
    805803                                                new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
    806804                                        // need to substitute for generic types so that casts are to concrete types
    807                                         alt.type = shallowCopy(alt.type.get());
    808805                                        PRINT( std::cerr << "  type is: " << alt.type; )
    809806                                        sub.apply( alt.type ); // also apply to designation??
     
    845842                                for ( InitAlternative & alt : ret ) {
    846843                                        PRINT( std::cerr << "iterating and adding designators" << std::endl; )
    847                                         alt.designation.get_and_mutate()->designators.emplace_front(
     844                                        alt.designation.get_and_mutate()->designators.emplace_front( 
    848845                                                new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
    849846                                }
     
    900897        class TupleIterator final : public AggregateIterator {
    901898        public:
    902                 TupleIterator( const CodeLocation & loc, const TupleType * inst )
    903                 : AggregateIterator(
    904                         loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members
     899                TupleIterator( const CodeLocation & loc, const TupleType * inst ) 
     900                : AggregateIterator( 
     901                        loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members 
    905902                ) {}
    906903
     
    929926                                return new UnionIterator{ loc, uit };
    930927                        } else {
    931                                 assertf(
    932                                         dynamic_cast< const EnumInstType * >( type )
    933                                                 || dynamic_cast< const TypeInstType * >( type ),
     928                                assertf( 
     929                                        dynamic_cast< const EnumInstType * >( aggr )
     930                                                || dynamic_cast< const TypeInstType * >( aggr ),
    934931                                        "Encountered unhandled ReferenceToType in createMemberIterator: %s",
    935932                                                toString( type ).c_str() );
     
    952949                using DesignatorChain = std::deque< ptr< Expr > >;
    953950                PRINT( std::cerr << "___findNext" << std::endl; )
    954 
     951               
    955952                // find all the d's
    956953                std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts;
     
    10161013                // set new designators
    10171014                assertf( ! objStack.empty(), "empty object stack when setting designation" );
    1018                 Designation * actualDesignation =
     1015                Designation * actualDesignation = 
    10191016                        new Designation{ designation->location, DesignatorChain{d} };
    10201017                objStack.back()->setPosition( d ); // destroys d
  • src/ResolvExpr/PolyCost.cc

    r1fcc2f3 rd056d0d  
    5858
    5959// TODO: When the old PolyCost is torn out get rid of the _new suffix.
    60 class PolyCost_new {
     60struct PolyCost_new {
     61        int result;
    6162        const ast::SymbolTable &symtab;
    62 public:
    63         int result;
    6463        const ast::TypeEnvironment &env_;
    6564
    66         PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env )
    67         : symtab( symtab ), result( 0 ), env_( env ) {}
     65        PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) :
     66                result( 0 ), symtab( symtab ), env_( env ) {}
    6867
    6968        void previsit( const ast::TypeInstType * type ) {
  • src/ResolvExpr/RenameVars.cc

    r1fcc2f3 rd056d0d  
    1919#include <utility>                 // for pair
    2020
    21 #include "AST/ForallSubstitutionTable.hpp"
    2221#include "AST/Pass.hpp"
    2322#include "AST/Type.hpp"
     
    3130#include "SynTree/Visitor.h"       // for acceptAll, maybeAccept
    3231
    33 #include "AST/Copy.hpp"
    34 
    3532namespace ResolvExpr {
    3633
     
    4037                int resetCount = 0;
    4138                ScopedMap< std::string, std::string > nameMap;
     39
    4240        public:
    43                 ast::ForallSubstitutionTable subs;
    44 
    4541                void reset() {
    4642                        level = 0;
     
    4844                }
    4945
     46                using mapConstIterator = ScopedMap< std::string, std::string >::const_iterator;
     47
    5048                void rename( TypeInstType * type ) {
    51                         auto it = nameMap.find( type->name );
     49                        mapConstIterator it = nameMap.find( type->name );
    5250                        if ( it != nameMap.end() ) {
    5351                                type->name = it->second;
     
    6765                                        // ditto for assertion names, the next level in
    6866                                        level++;
    69                                 }
    70                         }
     67                                        // acceptAll( td->assertions, *this );
     68                                } // for
     69                        } // if
    7170                }
    7271
     
    7877
    7978                const ast::TypeInstType * rename( const ast::TypeInstType * type ) {
    80                         // re-linking of base type handled by WithForallSubstitutor
    81 
    82                         // rename
    83                         auto it = nameMap.find( type->name );
     79                        mapConstIterator it = nameMap.find( type->name );
    8480                        if ( it != nameMap.end() ) {
    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;
     81                                ast::TypeInstType * mutType = ast::mutate( type );
     82                                mutType->name = it->second;
     83                    type = mutType;
    9084                        }
    91 
    9285                        return type;
    9386                }
     
    9588                template<typename NodeT>
    9689                const NodeT * openLevel( const NodeT * type ) {
    97                         if ( type->forall.empty() ) return 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;
    98100
    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
     101                                        ast::TypeDecl * decl = ast::mutate( td.get() );
     102                                        decl->name = newname;
     103                                        td = decl;
     104                                }
    115105                        }
    116                         // assertion above means `type = mutType;` is unnecessary
    117 
    118106                        return type;
    119107                }
    120108
    121                 void closeLevel( const ast::ParameterizedType * type ) {
    122                         if ( type->forall.empty() ) return;
    123 
    124                         nameMap.endScope();
     109                template<typename NodeT>
     110                const NodeT * closeLevel( const NodeT * type ) {
     111                        if ( !type->forall.empty() ) {
     112                                nameMap.endScope();
     113                        }
     114                        return type;
    125115                }
    126116        };
     
    129119        RenamingData renaming;
    130120
    131         struct RenameVars_old {
     121        struct RenameVars {
    132122                void previsit( TypeInstType * instType ) {
    133123                        renaming.openLevel( (Type*)instType );
     
    140130                        renaming.closeLevel( type );
    141131                }
    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;
    147132
    148133                const ast::FunctionType * previsit( const ast::FunctionType * type ) {
     
    161146                        return renaming.rename( renaming.openLevel( type ) );
    162147                }
    163                 void postvisit( const ast::ParameterizedType * type ) {
    164                         renaming.closeLevel( type );
     148                const ast::ParameterizedType * postvisit( const ast::ParameterizedType * type ) {
     149                        return renaming.closeLevel( type );
    165150                }
    166151        };
     
    169154
    170155void renameTyVars( Type * t ) {
    171         PassVisitor<RenameVars_old> renamer;
     156        PassVisitor<RenameVars> renamer;
    172157        t->accept( renamer );
    173158}
    174159
    175160const ast::Type * renameTyVars( const ast::Type * t ) {
    176         ast::Type *tc = ast::deepCopy(t);
    177         ast::Pass<RenameVars_new> renamer;
    178 //      return t->accept( renamer );
    179         return tc->accept( renamer );
     161        ast::Pass<RenameVars> renamer;
     162        return t->accept( renamer );
    180163}
    181164
  • src/ResolvExpr/ResolveTypeof.cc

    r1fcc2f3 rd056d0d  
    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 previsit( const ast::TypeofType * ) { visit_children = false; }
     122                void premutate( const ast::TypeofType * ) { visit_children = false; }
    123123
    124                 const ast::Type * postvisit( const ast::TypeofType * typeofType ) {
     124                const ast::Type * postmutate( 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.release();
     155                        return newType;
    156156                }
    157157        };
  • src/ResolvExpr/Resolver.cc

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

    r1fcc2f3 rd056d0d  
    99// Author           : Aaron B. Moss
    1010// Created On       : Mon Jun 10 17:45:00 2019
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct  1 13:56:00 2019
    13 // Update Count     : 2
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Mon Jun 10 17:45:00 2019
     13// Update Count     : 1
    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(), false, symtab, env );
    310 
     308                                        cost += computeConversionCost( 
     309                                                assn.match.adjType, assn.decl->get_type(), 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

    r1fcc2f3 rd056d0d  
    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

    r1fcc2f3 rd056d0d  
    1010// Created On       : Tue Oct 02 15:50:00 2018
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jul  3 11:07:00 2019
    13 // Update Count     : 3
    14 //
    15 
    16 #include <cassert>
     12// Last Modified On : Wed Jun 19 10:43:00 2019
     13// Update Count     : 2
     14//
     15
    1716#include <limits>
    1817#include <list>
     
    130129                        typename std::add_pointer<ast::Type const *(typename T::value_type const &)>::type;
    131130
    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 
    140131                // Update the minimum to the new lowest non-none value.
    141132                template<typename T>
     
    143134                        for ( const auto & node : list ) {
    144135                                count = -1;
    145                                 maybe_accept( mapper( node ) );
     136                                mapper( node )->accept( *visitor );
    146137                                if ( count != -1 && count < minimum ) minimum = count;
    147138                        }
  • src/ResolvExpr/Unify.cc

    r1fcc2f3 rd056d0d  
    2525#include <vector>
    2626
    27 #include "AST/Copy.hpp"
    2827#include "AST/Decl.hpp"
    2928#include "AST/Node.hpp"
    3029#include "AST/Pass.hpp"
    31 #include "AST/Print.hpp"
    3230#include "AST/Type.hpp"
    3331#include "AST/TypeEnvironment.hpp"
     
    137135                findOpenVars( newSecond, open, closed, need, have, FirstOpen );
    138136
    139                 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     137                return unifyExact(
     138                        newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
    140139        }
    141140
     
    149148                newFirst->get_qualifiers() = Type::Qualifiers();
    150149                newSecond->get_qualifiers() = Type::Qualifiers();
    151 
     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;
    152159                bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    153160                delete newFirst;
     
    163170                ast::AssertionSet need, have;
    164171
    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);
     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 );
    171177
    172178                return unifyExact(
    173                         env.apply( newFirst  ).node,
    174                         env.apply( newSecond ).node,
    175                         newEnv, need, have, open, noWiden(), symtab );
     179                        newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
    176180        }
    177181
     
    322326
    323327        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;
    324333                AssertionSet::iterator i = assertions.find( assert );
    325334                if ( i != assertions.end() ) {
     335///     std::cerr << "found it!" << std::endl;
    326336                        i->second.isUsed = true;
    327337                } // if
     
    933943
    934944        private:
    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 ) {
     945                template< typename RefType >
     946                const RefType * handleRefType( const RefType * inst, const ast::Type * other ) {
    939947                        // check that the other type is compatible and named the same
    940                         auto otherInst = dynamic_cast< const XInstType * >( other );
    941                         this->result = otherInst && inst->name == otherInst->name;
     948                        auto otherInst = dynamic_cast< const RefType * >( other );
     949                        result = otherInst && inst->name == otherInst->name;
    942950                        return otherInst;
    943951                }
     
    960968                }
    961969
    962                 template< typename XInstType >
    963                 void handleGenericRefType( const XInstType * inst, const ast::Type * other ) {
     970                template< typename RefType >
     971                void handleGenericRefType( const RefType * inst, const ast::Type * other ) {
    964972                        // check that other type is compatible and named the same
    965                         const XInstType * otherInst = handleRefType( inst, other );
    966                         if ( ! this->result ) return;
     973                        const RefType * inst2 = handleRefType( inst, other );
     974                        if ( ! inst2 ) return;
    967975
    968976                        // check that parameters of types unify, if any
    969977                        const std::vector< ast::ptr< ast::Expr > > & params = inst->params;
    970                         const std::vector< ast::ptr< ast::Expr > > & params2 = otherInst->params;
     978                        const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params;
    971979
    972980                        auto it = params.begin();
     
    11941202                // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and
    11951203                // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1
    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);
     1204                ast::ptr<ast::Type> t1{ type1 }, t2{ type2 };
     1205                reset_qualifiers( t1 );
     1206                reset_qualifiers( t2 );
    12021207
    12031208                if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
     1209                        t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
     1210
    12041211                        // if exact unification on unqualified types, try to merge qualifiers
    12051212                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
    1206                                 t1->qualifiers = q1 | q2;
    1207                                 common = t1;
     1213                                common = type1;
     1214                                reset_qualifiers( common, q1 | q2 );
    12081215                                return true;
    12091216                        } else {
     
    12121219
    12131220                } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {
     1221                        t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
     1222
    12141223                        // no exact unification, but common type
    1215                         auto c = shallowCopy(common.get());
    1216                         c->qualifiers = q1 | q2;
    1217                         common = c;
     1224                        reset_qualifiers( common, q1 | q2 );
    12181225                        return true;
    12191226                } else {
  • src/ResolvExpr/typeops.h

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

    r1fcc2f3 rd056d0d  
    2121
    2222#include "AST/Decl.hpp"
    23 #include "AST/Eval.hpp"
    2423#include "AST/Expr.hpp"
    2524#include "AST/Init.hpp"
     
    265264                }
    266265
    267                 ast::ptr< ast::Expr > begin, end;
    268                 std::string cmp, update;
     266                ast::ptr< ast::Expr > begin, end, cmp, update;
    269267
    270268                if ( forward ) {
     
    272270                        begin = ast::ConstantExpr::from_int( loc, 0 );
    273271                        end = array->dimension;
    274                         cmp = "?<?";
    275                         update = "++?";
     272                        cmp = new ast::NameExpr{ loc, "?<?" };
     273                        update = new ast::NameExpr{ loc, "++?" };
    276274                } else {
    277275                        // generate: for ( int i = N-1; i >= 0; --i )
    278                         begin = ast::call(
    279                                 loc, "?-?", array->dimension, ast::ConstantExpr::from_int( loc, 1 ) );
     276                        begin = new ast::UntypedExpr{
     277                                loc, new ast::NameExpr{ loc, "?-?" },
     278                                { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } };
    280279                        end = ast::ConstantExpr::from_int( loc, 0 );
    281                         cmp = "?>=?";
    282                         update = "--?";
     280                        cmp = new ast::NameExpr{ loc, "?>=?" };
     281                        update = new ast::NameExpr{ loc, "--?" };
    283282                }
    284283
     
    286285                        loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },
    287286                        new ast::SingleInit{ loc, begin } };
    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 );
     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 } } };
    295297               
    296298                // srcParam must keep track of the array indices to build the source parameter and/or
    297299                // array list initializer
    298                 srcParam.addArrayIndex( indexVar, array->dimension );
     300                srcParam.addArrayIndex( new ast::VariableExpr{ loc, index }, array->dimension );
    299301
    300302                // for stmt's body, eventually containing call
     
    382384                if ( isUnnamedBitfield( obj ) ) return {};
    383385
    384                 ast::ptr< ast::Type > addCast;
     386                ast::ptr< ast::Type > addCast = nullptr;
    385387                if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
    386388                        assert( dstParam->result );
  • src/SynTree/Statement.h

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

    r1fcc2f3 rd056d0d  
    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 ) ) );
    131132                        }
    132133                        if ( first ) {
  • src/Tuples/Explode.h

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

    r1fcc2f3 rd056d0d  
    465465                                        // resolve ctor/dtor for the new object
    466466                                        ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit(
    467                                                         InitTweak::genCtorInit( location, ret ), spotter.crntFinder.localSyms );
     467                                                        InitTweak::genCtorInit( location, ret ), spotter.crntFinder.symtab );
    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.localSyms, env };
     562                                        ResolvExpr::CandidateFinder finder{ spotter.crntFinder.symtab, 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.localSyms, back_inserter(lhs), true );
     611                                        explode( *lhsCand, crntFinder.symtab, 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.localSyms, back_inserter(rhs), true );
     631                                                                explode( *rhsCand, crntFinder.symtab, 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.localSyms, back_inserter(rhs), true );
     650                                                        explode( rhsCand, crntFinder.symtab, back_inserter(rhs), true );
    651651                                                        matcher.reset(
    652652                                                                new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
     
    678678                                )
    679679
    680                                 ResolvExpr::CandidateFinder finder{ crntFinder.localSyms, matcher->env };
     680                                ResolvExpr::CandidateFinder finder{ crntFinder.symtab, matcher->env };
    681681
    682682                                try {
  • src/Tuples/TupleExpansion.cc

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

    r1fcc2f3 rd056d0d  
    2929#include <string>                           // for char_traits, operator<<
    3030
    31 #include "AST/Convert.hpp"
    3231#include "CompilationState.h"
    3332#include "../config.h"                      // for CFA_LIBDIR
     
    304303                } // if
    305304
    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 
     305                PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
    313306                if ( exprp ) {
    314307                        dump( translationUnit );
Note: See TracChangeset for help on using the changeset viewer.