Changes in / [7030dab:057298e]


Ignore:
Files:
1 added
7 deleted
47 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Attribute.hpp

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

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

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

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

    r7030dab r057298e  
    3333
    3434// Must be included in *all* AST classes; should be #undef'd at the end of the file
    35 #define MUTATE_FRIEND \
    36     template<typename node_t> friend node_t * mutate(const node_t * node); \
    37         template<typename node_t> friend node_t * shallowCopy(const node_t * node);
     35#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
    3836
    3937namespace ast {
     
    9088        virtual const Type * get_type() const = 0;
    9189        /// Set type of this declaration. May be verified by subclass
    92         virtual void set_type( const Type * ) = 0;
     90        virtual void set_type(Type *) = 0;
    9391
    9492        const DeclWithType * accept( Visitor & v ) const override = 0;
     
    113111
    114112        const Type* get_type() const override { return type; }
    115         void set_type( const Type * ty ) override { type = ty; }
     113        void set_type( Type * ty ) override { type = ty; }
    116114
    117115        const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
     
    135133
    136134        const Type * get_type() const override;
    137         void set_type( const Type * t ) override;
     135        void set_type(Type * t) override;
    138136
    139137        bool has_body() const { return stmts; }
     
    152150        std::vector<ptr<DeclWithType>> assertions;
    153151
    154         NamedTypeDecl(
    155                 const CodeLocation & loc, const std::string & name, Storage::Classes storage,
    156                 const Type * b, Linkage::Spec spec = Linkage::Cforall )
     152        NamedTypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
     153                Type* b, Linkage::Spec spec = Linkage::Cforall )
    157154        : Decl( loc, name, storage, spec ), base( b ), params(), assertions() {}
    158155
     
    189186        };
    190187
    191         TypeDecl(
    192                 const CodeLocation & loc, const std::string & name, Storage::Classes storage,
    193                 const Type * b, TypeVar::Kind k, bool s, const Type * i = nullptr )
    194         : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeVar::Ttype || s ),
    195           init( i ) {}
     188        TypeDecl( const CodeLocation & loc, const std::string & name, Storage::Classes storage, Type * b,
     189                          Kind k, bool s, Type * i = nullptr )
     190                : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == Ttype || s ),
     191                init( i ) {}
    196192
    197193        const char * typeString() const override;
  • src/AST/Expr.cpp

    r7030dab r057298e  
    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 {
     
    156139: Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {}
    157140
    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 }
    162 
    163141// --- KeywordCastExpr
    164142
    165143const char * KeywordCastExpr::targetString() const {
    166144        return AggregateDecl::aggrString( target );
    167 }
    168 
    169 // --- UntypedMemberExpr
    170 
    171 bool UntypedMemberExpr::get_lvalue() const {
    172         return aggregate->get_lvalue();
    173145}
    174146
     
    181153        assert( aggregate->result );
    182154
    183         // Deep copy on result type avoids mutation on transitively multiply referenced object.
    184         //
    185         // Example, adapted from parts of builtins and bootloader:
    186         //
    187         // forall(dtype T)
    188         // struct __Destructor {
    189         //   T * object;
    190         //   void (*dtor)(T *);
    191         // };
    192         //
    193         // forall(dtype S)
    194         // void foo(__Destructor(S) &d) {
    195         //   if (d.dtor) {  // here
    196         //   }
    197         // }
    198         //
    199         // Let e be the "d.dtor" guard espression, which is MemberExpr after resolve.  Let d be the
    200         // declaration of member __Destructor.dtor (an ObjectDecl), as accessed via the top-level
    201         // declaration of __Destructor.  Consider the types e.result and d.type.  In the old AST, one
    202         // is a clone of the other.  Ordinary new-AST use would set them up as a multiply-referenced
    203         // object.
    204         //
    205         // e.result: PointerType
    206         // .base: FunctionType
    207         // .params.front(): ObjectDecl, the anonymous parameter of type T*
    208         // .type: PointerType
    209         // .base: TypeInstType
    210         // let x = that
    211         // let y = similar, except start from d.type
    212         //
    213         // Consider two code lines down, genericSubstitution(...).apply(result).
    214         //
    215         // Applying this chosen-candidate's type substitution means modifying x, substituting
    216         // S for T.  This mutation should affect x and not y.
    217 
    218         result = deepCopy(mem->get_type());
    219 
     155        // take ownership of member type
     156        result = mem->get_type();
    220157        // substitute aggregate generic parameters into member type
    221158        genericSubstitution( aggregate->result ).apply( result );
    222         // ensure appropriate restrictions from aggregate type
    223         add_qualifiers( result, aggregate->result->qualifiers );
    224 }
    225 
    226 MemberExpr::MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
    227     MemberExpr::NoOpConstruction overloadSelector )
    228 : Expr( loc ), member( mem ), aggregate( agg ) {
    229         assert( member );
    230         assert( aggregate );
    231         assert( aggregate->result );
    232         (void) overloadSelector;
    233 }
    234 
    235 bool MemberExpr::get_lvalue() const {
    236         // This is actually wrong by C, but it works with our current set-up.
    237         return true;
     159        // ensure lvalue and appropriate restrictions from aggregate type
     160        add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue );
    238161}
    239162
     
    247170        assert( var );
    248171        assert( var->get_type() );
    249         result = shallowCopy( var->get_type() );
    250 }
    251 
    252 bool VariableExpr::get_lvalue() const {
    253         // It isn't always an lvalue, but it is never an rvalue.
    254         return true;
     172        result = var->get_type();
     173        add_qualifiers( result, CV::Lvalue );
    255174}
    256175
     
    338257        const CodeLocation & loc, const Expr * a1, const Expr * a2, LogicalFlag ia )
    339258: Expr( loc, new BasicType{ BasicType::SignedInt } ), arg1( a1 ), arg2( a2 ), isAnd( ia ) {}
    340 
    341 // --- CommaExpr
    342 bool CommaExpr::get_lvalue() const {
    343         // This is wrong by C, but the current implementation uses it.
    344         // (ex: Specialize, Lvalue and Box)
    345         return arg2->get_lvalue();
    346 }
    347259
    348260// --- ConstructorExpr
     
    364276        assert( t && i );
    365277        result = t;
    366 }
    367 
    368 bool CompoundLiteralExpr::get_lvalue() const {
    369         return true;
     278        add_qualifiers( result, CV::Lvalue );
    370279}
    371280
     
    384293        // like MemberExpr, TupleIndexExpr is always an lvalue
    385294        result = type->types[ index ];
    386 }
    387 
    388 bool TupleIndexExpr::get_lvalue() const {
    389         return tuple->get_lvalue();
     295        add_qualifiers( result, CV::Lvalue );
    390296}
    391297
  • src/AST/Expr.hpp

    r7030dab r057298e  
    3131
    3232// Must be included in *all* AST classes; should be #undef'd at the end of the file
    33 #define MUTATE_FRIEND \
    34     template<typename node_t> friend node_t * mutate(const node_t * node); \
    35         template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    36 
     33#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
    3734
    3835class ConverterOldToNew;
     
    188185
    189186        Expr * set_extension( bool ex ) { extension = ex; return this; }
    190         virtual bool get_lvalue() const;
    191187
    192188        virtual const Expr * accept( Visitor & v ) const override = 0;
     
    205201        ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} );
    206202
    207         bool get_lvalue() const final;
    208 
    209203        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    210204private:
     
    221215        UntypedExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} )
    222216        : Expr( loc ), func( f ), args( std::move(as) ) {}
    223 
    224         bool get_lvalue() const final;
    225217
    226218        /// Creates a new dereference expression
     
    299291        CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {}
    300292
    301         bool get_lvalue() const final;
    302 
    303293        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    304294private:
     
    348338        : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); }
    349339
    350         bool get_lvalue() const final;
    351 
    352340        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    353341private:
     
    364352        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg );
    365353
    366         bool get_lvalue() const final;
    367 
    368354        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    369355private:
    370356        MemberExpr * clone() const override { return new MemberExpr{ *this }; }
    371357        MUTATE_FRIEND
    372 
    373         // Custructor overload meant only for AST conversion
    374         enum NoOpConstruction { NoOpConstructionChosen };
    375         MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
    376             NoOpConstruction overloadSelector );
    377         friend class ::ConverterOldToNew;
    378         friend class ::ConverterNewToOld;
    379358};
    380359
     
    386365        VariableExpr( const CodeLocation & loc );
    387366        VariableExpr( const CodeLocation & loc, const DeclWithType * v );
    388 
    389         bool get_lvalue() const final;
    390367
    391368        /// generates a function pointer for a given function
     
    555532
    556533        CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
    557         : Expr( loc ), arg1( a1 ), arg2( a2 ) {
    558                 this->result = a2->result;
    559         }
    560 
    561         bool get_lvalue() const final;
     534        : Expr( loc ), arg1( a1 ), arg2( a2 ) {}
    562535
    563536        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    632605        CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i );
    633606
    634         bool get_lvalue() const final;
    635 
    636607        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    637608private:
     
    689660
    690661        TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i );
    691 
    692         bool get_lvalue() const final;
    693662
    694663        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Init.hpp

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

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

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

    r7030dab r057298e  
    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 >
     
    205202        container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
    206203
    207         /// Mutate forall-list, accounting for presence of type substitution map
    208         template<typename node_t>
    209         void mutate_forall( const node_t *& );
    210 
    211204public:
    212205        /// Logic to call the accept and mutate the parent if needed, delegates call to accept
     
    217210        /// Internal RAII guard for symbol table features
    218211        struct guard_symtab {
    219                 guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass.pass, 0); }
    220                 ~guard_symtab()                                   { __pass::symtab::leave(pass.pass, 0); }
     212                guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass, 0); }
     213                ~guard_symtab()                                   { __pass::symtab::leave(pass, 0); }
    221214                Pass<pass_t> & pass;
    222215        };
     
    224217        /// Internal RAII guard for scope features
    225218        struct guard_scope {
    226                 guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass.pass, 0); }
    227                 ~guard_scope()                                   { __pass::scope::leave(pass.pass, 0); }
     219                guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass, 0); }
     220                ~guard_scope()                                   { __pass::scope::leave(pass, 0); }
    228221                Pass<pass_t> & pass;
    229         };
    230 
    231         /// Internal RAII guard for forall substitutions
    232         struct guard_forall_subs {
    233                 guard_forall_subs( Pass<pass_t> & pass, const ParameterizedType * type )
    234                 : pass( pass ), type( type ) { __pass::forall::enter(pass.pass, 0, type ); }
    235                 ~guard_forall_subs()         { __pass::forall::leave(pass.pass, 0, type ); }
    236                 Pass<pass_t> & pass;
    237                 const ParameterizedType * type;
    238222        };
    239223
     
    330314        SymbolTable symtab;
    331315};
    332 
    333 /// Use when the templated visitor needs to keep TypeInstType instances properly linked to TypeDecl
    334 struct WithForallSubstitutor {
    335         ForallSubstitutionTable subs;
    336 };
    337 
    338316}
    339317
  • src/AST/Pass.impl.hpp

    r7030dab r057298e  
    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 );
     
    966951        // For now this isn't visited, it is unclear if this causes problem
    967952        // if all tests are known to pass, remove this code
    968         VISIT(
    969                 maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
    970         )
     953        // VISIT(
     954        //      maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
     955        // )
    971956
    972957        VISIT_END( Stmt, node );
     
    16941679        VISIT_START( node );
    16951680
    1696         VISIT({
    1697                 guard_forall_subs forall_guard { *this, node };
    1698                 mutate_forall( node );
     1681        VISIT(
     1682                maybe_accept( node, &FunctionType::forall  );
    16991683                maybe_accept( node, &FunctionType::returns );
    17001684                maybe_accept( node, &FunctionType::params  );
    1701         })
     1685        )
    17021686
    17031687        VISIT_END( Type, node );
     
    17141698        VISIT({
    17151699                guard_symtab guard { *this };
    1716                 guard_forall_subs forall_guard { *this, node };
    1717                 mutate_forall( node );
     1700                maybe_accept( node, &StructInstType::forall );
    17181701                maybe_accept( node, &StructInstType::params );
    17191702        })
     
    17281711        VISIT_START( node );
    17291712
    1730         __pass::symtab::addUnion( pass, 0, node->name );
    1731 
    1732         VISIT({
     1713        __pass::symtab::addStruct( pass, 0, node->name );
     1714
     1715        {
    17331716                guard_symtab guard { *this };
    1734                 guard_forall_subs forall_guard { *this, node };
    1735                 mutate_forall( node );
     1717                maybe_accept( node, &UnionInstType::forall );
    17361718                maybe_accept( node, &UnionInstType::params );
    1737         })
     1719        }
    17381720
    17391721        VISIT_END( Type, node );
     
    17461728        VISIT_START( node );
    17471729
    1748         VISIT({
    1749                 guard_forall_subs forall_guard { *this, node };
    1750                 mutate_forall( node );
     1730        VISIT(
     1731                maybe_accept( node, &EnumInstType::forall );
    17511732                maybe_accept( node, &EnumInstType::params );
    1752         })
     1733        )
    17531734
    17541735        VISIT_END( Type, node );
     
    17611742        VISIT_START( node );
    17621743
    1763         VISIT({
    1764                 guard_forall_subs forall_guard { *this, node };
    1765                 mutate_forall( node );
     1744        VISIT(
     1745                maybe_accept( node, &TraitInstType::forall );
    17661746                maybe_accept( node, &TraitInstType::params );
    1767         })
     1747        )
    17681748
    17691749        VISIT_END( Type, node );
     
    17771757
    17781758        VISIT(
    1779                 {
    1780                         guard_forall_subs forall_guard { *this, node };
    1781                         mutate_forall( node );
    1782                         maybe_accept( node, &TypeInstType::params );
    1783                 }
    1784                 // ensure that base re-bound if doing substitution
    1785                 __pass::forall::replace( pass, 0, node );
     1759                maybe_accept( node, &TypeInstType::forall );
     1760                maybe_accept( node, &TypeInstType::params );
    17861761        )
    17871762
     
    19321907                                guard_symtab guard { *this };
    19331908                                auto new_node = p.second->accept( *this );
    1934                                 if (new_node != p.second) mutated = true;
     1909                                if (new_node != p.second) mutated = false;
    19351910                                new_map.insert({ p.first, new_node });
    19361911                        }
     
    19481923                                guard_symtab guard { *this };
    19491924                                auto new_node = p.second->accept( *this );
    1950                                 if (new_node != p.second) mutated = true;
     1925                                if (new_node != p.second) mutated = false;
    19511926                                new_map.insert({ p.first, new_node });
    19521927                        }
  • src/AST/Pass.proto.hpp

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

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

    r7030dab r057298e  
    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
     
    9290// GENERATED END
    9391
    94 // --- ParameterizedType
    95 
    96 void ParameterizedType::initWithSub(
    97         const ParameterizedType & o, Pass< ForallSubstitutor > & sub
    98 ) {
    99         forall = sub.pass( o.forall );
    100 }
    101 
    10292// --- FunctionType
    103 
    104 FunctionType::FunctionType( const FunctionType & o )
    105 : ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(),
    106   isVarArgs( o.isVarArgs ) {
    107         Pass< ForallSubstitutor > sub;
    108         initWithSub( o, sub );           // initialize substitution map
    109         returns = sub.pass( o.returns ); // apply to return and parameter types
    110         params = sub.pass( o.params );
    111 }
    11293
    11394namespace {
     
    125106
    126107// --- ReferenceToType
    127 
    128 void ReferenceToType::initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub ) {
    129         ParameterizedType::initWithSub( o, sub ); // initialize substitution
    130         params = sub.pass( o.params );            // apply to parameters
    131 }
    132 
    133 ReferenceToType::ReferenceToType( const ReferenceToType & o )
    134 : ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ),
    135   hoistType( o.hoistType ) {
    136         Pass< ForallSubstitutor > sub;
    137         initWithSub( o, sub );
    138 }
    139 
    140108std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const {
    141109        assertf( aggr(), "Must have aggregate to perform lookup" );
     
    150118// --- StructInstType
    151119
    152 StructInstType::StructInstType(
    153         const StructDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
    154 : ReferenceToType( b->name, q, move(as) ), base( b ) {}
     120StructInstType::StructInstType( const StructDecl * b, CV::Qualifiers q,
     121        std::vector<ptr<Attribute>>&& as )
     122: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
    155123
    156124bool StructInstType::isComplete() const { return base ? base->body : false; }
     
    158126// --- UnionInstType
    159127
    160 UnionInstType::UnionInstType(
    161         const UnionDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
    162 : ReferenceToType( b->name, q, move(as) ), base( b ) {}
     128UnionInstType::UnionInstType( const UnionDecl * b, CV::Qualifiers q,
     129        std::vector<ptr<Attribute>>&& as )
     130: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
    163131
    164132bool UnionInstType::isComplete() const { return base ? base->body : false; }
     
    166134// --- EnumInstType
    167135
    168 EnumInstType::EnumInstType(
    169         const EnumDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
    170 : ReferenceToType( b->name, q, move(as) ), base( b ) {}
     136EnumInstType::EnumInstType( const EnumDecl * b, CV::Qualifiers q,
     137        std::vector<ptr<Attribute>>&& as )
     138: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
    171139
    172140bool EnumInstType::isComplete() const { return base ? base->body : false; }
     
    174142// --- TraitInstType
    175143
    176 TraitInstType::TraitInstType(
    177         const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
    178 : ReferenceToType( b->name, q, move(as) ), base( b ) {}
     144TraitInstType::TraitInstType( const TraitDecl * b, CV::Qualifiers q,
     145        std::vector<ptr<Attribute>>&& as )
     146: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
    179147
    180148// --- TypeInstType
    181 
    182 TypeInstType::TypeInstType( const TypeInstType & o )
    183 : ReferenceToType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {
    184         Pass< ForallSubstitutor > sub;
    185         initWithSub( o, sub );      // initialize substitution
    186         base = sub.pass( o.base );  // apply to base type
    187 }
    188149
    189150void TypeInstType::set_base( const TypeDecl * b ) {
     
    197158
    198159TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q )
    199 : Type( q ), types( move(ts) ), members() {
     160: Type( q ), types( std::move(ts) ), members() {
    200161        // This constructor is awkward. `TupleType` needs to contain objects so that members can be
    201162        // named, but members without initializer nodes end up getting constructors, which breaks
  • src/AST/Type.hpp

    r7030dab r057298e  
    2929
    3030// Must be included in *all* AST classes; should be #undef'd at the end of the file
    31 #define MUTATE_FRIEND \
    32     template<typename node_t> friend node_t * mutate(const node_t * node); \
    33         template<typename node_t> friend node_t * shallowCopy(const node_t * node);
     31#define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
    3432
    3533namespace ast {
    36 
    37 template< typename T > class Pass;
    38 
    39 struct ForallSubstitutor;
    4034
    4135class Type : public Node {
     
    5044        bool is_volatile() const { return qualifiers.is_volatile; }
    5145        bool is_restrict() const { return qualifiers.is_restrict; }
     46        bool is_lvalue() const { return qualifiers.is_lvalue; }
    5247        bool is_mutex() const { return qualifiers.is_mutex; }
    5348        bool is_atomic() const { return qualifiers.is_atomic; }
     
    5651        Type * set_volatile( bool v ) { qualifiers.is_volatile = v; return this; }
    5752        Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; }
     53        Type * set_lvalue( bool v ) { qualifiers.is_lvalue = v; return this; }
    5854        Type * set_mutex( bool v ) { qualifiers.is_mutex = v; return this; }
    5955        Type * set_atomic( bool v ) { qualifiers.is_atomic = v; return this; }
     
    167163        static const char *typeNames[];
    168164
    169         BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     165        BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 
    170166        : Type(q, std::move(as)), kind(k) {}
    171167
     
    269265/// Base type for potentially forall-qualified types
    270266class ParameterizedType : public Type {
    271 protected:
    272         /// initializes forall with substitutor
    273         void initWithSub( const ParameterizedType & o, Pass< ForallSubstitutor > & sub );
    274267public:
    275268        using ForallList = std::vector<ptr<TypeDecl>>;
     
    283276        ParameterizedType( CV::Qualifiers q, std::vector<ptr<Attribute>> && as = {} )
    284277        : Type(q, std::move(as)), forall() {}
    285 
    286         // enforce use of ForallSubstitutor to copy parameterized type
    287         ParameterizedType( const ParameterizedType & ) = delete;
    288 
    289         ParameterizedType( ParameterizedType && ) = default;
    290 
    291         // no need to change destructor, and operator= deleted in Node
    292278
    293279private:
     
    315301        : ParameterizedType(q), returns(), params(), isVarArgs(va) {}
    316302
    317         FunctionType( const FunctionType & o );
    318 
    319303        /// true if either the parameters or return values contain a tttype
    320304        bool isTtype() const;
     
    330314/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
    331315class ReferenceToType : public ParameterizedType {
    332 protected:
    333         /// Initializes forall and parameters based on substitutor
    334         void initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub );
    335316public:
    336317        std::vector<ptr<Expr>> params;
     
    338319        bool hoistType = false;
    339320
    340         ReferenceToType(
    341                 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     321        ReferenceToType( const std::string& n, CV::Qualifiers q = {},
     322                std::vector<ptr<Attribute>> && as = {} )
    342323        : ParameterizedType(q, std::move(as)), params(), name(n) {}
    343 
    344         ReferenceToType( const ReferenceToType & o );
    345324
    346325        /// Gets aggregate declaration this type refers to
     
    359338        readonly<StructDecl> base;
    360339
    361         StructInstType(
    362                 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     340        StructInstType( const std::string& n, CV::Qualifiers q = {},
     341                std::vector<ptr<Attribute>> && as = {} )
    363342        : ReferenceToType( n, q, std::move(as) ), base() {}
    364 
    365         StructInstType(
    366                 const StructDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
     343        StructInstType( const StructDecl * b, CV::Qualifiers q = {},
     344                std::vector<ptr<Attribute>> && as = {} );
    367345
    368346        bool isComplete() const override;
     
    381359        readonly<UnionDecl> base;
    382360
    383         UnionInstType(
    384                 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     361        UnionInstType( const std::string& n, CV::Qualifiers q = {},
     362                std::vector<ptr<Attribute>> && as = {} )
    385363        : ReferenceToType( n, q, std::move(as) ), base() {}
    386 
    387         UnionInstType(
    388                 const UnionDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
     364        UnionInstType( const UnionDecl * b, CV::Qualifiers q = {},
     365                std::vector<ptr<Attribute>> && as = {} );
    389366
    390367        bool isComplete() const override;
     
    403380        readonly<EnumDecl> base;
    404381
    405         EnumInstType(
    406                 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     382        EnumInstType( const std::string& n, CV::Qualifiers q = {},
     383                std::vector<ptr<Attribute>> && as = {} )
    407384        : ReferenceToType( n, q, std::move(as) ), base() {}
    408 
    409         EnumInstType(
    410                 const EnumDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
     385        EnumInstType( const EnumDecl * b, CV::Qualifiers q = {},
     386                std::vector<ptr<Attribute>> && as = {} );
    411387
    412388        bool isComplete() const override;
     
    425401        readonly<TraitDecl> base;
    426402
    427         TraitInstType(
    428                 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     403        TraitInstType( const std::string& n, CV::Qualifiers q = {},
     404                std::vector<ptr<Attribute>> && as = {} )
    429405        : ReferenceToType( n, q, std::move(as) ), base() {}
    430 
    431         TraitInstType(
    432                 const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
     406        TraitInstType( const TraitDecl * b, CV::Qualifiers q = {},
     407                std::vector<ptr<Attribute>> && as = {} );
    433408
    434409        // not meaningful for TraitInstType
     
    449424        TypeDecl::Kind kind;
    450425
    451         TypeInstType(
    452                 const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
     426        TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
    453427                std::vector<ptr<Attribute>> && as = {} )
    454428        : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
     
    456430                std::vector<ptr<Attribute>> && as = {} )
    457431        : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
    458 
    459         TypeInstType( const TypeInstType & o );
    460432
    461433        /// sets `base`, updating `kind` correctly
  • src/AST/TypeEnvironment.hpp

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

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

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

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

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

    r7030dab r057298e  
    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) \
     
    590589        AST/DeclReplacer.cpp \
    591590        AST/Expr.cpp \
    592         AST/ForallSubstitutionTable.cpp \
    593591        AST/GenericSubstitution.cpp \
    594592        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

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

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

    r7030dab r057298e  
    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;
    601601                ast::ptr< ast::Type > & targetType;
    602602
    603                 enum Errors {
    604                         NotFound,
    605                         NoMatch,
    606                         ArgsToFew,
    607                         ArgsToMany,
    608                         RetsToFew,
    609                         RetsToMany,
    610                         NoReason
    611                 };
    612 
    613                 struct {
    614                         Errors code = NotFound;
    615                 } reason;
    616 
    617603                Finder( CandidateFinder & f )
    618                 : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
     604                : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
    619605                  targetType( f.targetType ) {}
    620 
     606               
    621607                void previsit( const ast::Node * ) { visit_children = false; }
    622608
     
    625611                void addCandidate( Args &&... args ) {
    626612                        candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } );
    627                         reason.code = NoReason;
    628613                }
    629614
     
    654639
    655640                /// Completes a function candidate with arguments located
    656                 void validateFunctionCandidate(
    657                         const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,
    658                         CandidateList & out
     641                void validateFunctionCandidate( 
     642                        const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 
     643                        CandidateList & out 
    659644                ) {
    660                         ast::ApplicationExpr * appExpr =
     645                        ast::ApplicationExpr * appExpr = 
    661646                                new ast::ApplicationExpr{ func->expr->location, func->expr };
    662647                        // sum cost and accumulate arguments
     
    672657                        appExpr->args = move( vargs );
    673658                        // build and validate new candidate
    674                         auto newCand =
     659                        auto newCand = 
    675660                                std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );
    676661                        PRINT(
     
    684669                /// Builds a list of candidates for a function, storing them in out
    685670                void makeFunctionCandidates(
    686                         const CandidateRef & func, const ast::FunctionType * funcType,
     671                        const CandidateRef & func, const ast::FunctionType * funcType, 
    687672                        const ExplodedArgs_new & args, CandidateList & out
    688673                ) {
     
    691676                        ast::TypeEnvironment funcEnv{ func->env };
    692677                        makeUnifiableVars( funcType, funcOpen, funcNeed );
    693                         // add all type variables as open variables now so that those not used in the
    694                         // 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
    695680                        funcEnv.add( funcType->forall );
    696681
     
    698683                                // attempt to narrow based on expected target type
    699684                                const ast::Type * returnType = funcType->returns.front()->get_type();
    700                                 if ( ! unify(
    701                                         returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
     685                                if ( ! unify( 
     686                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 
    702687                                ) {
    703688                                        // unification failed, do not pursue this candidate
     
    713698                        for ( const ast::DeclWithType * param : funcType->params ) {
    714699                                auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
    715                                 // 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 
    716701                                // matches
    717                                 if ( ! instantiateArgument(
     702                                if ( ! instantiateArgument( 
    718703                                        obj->type, obj->init, args, results, genStart, symtab ) ) return;
    719704                        }
     
    765750                                                        if ( expl.exprs.empty() ) {
    766751                                                                results.emplace_back(
    767                                                                         results[i], move( env ), copy( results[i].need ),
    768                                                                         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, 
    769754                                                                        expl.cost );
    770755
     
    775760                                                        results.emplace_back(
    776761                                                                i, expl.exprs.front(), move( env ), copy( results[i].need ),
    777                                                                 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost,
     762                                                                copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 
    778763                                                                expl.exprs.size() == 1 ? 0 : 1, j );
    779764                                                }
     
    795780                /// Adds implicit struct-conversions to the alternative list
    796781                void addAnonConversions( const CandidateRef & cand ) {
    797                         // adds anonymous member interpretations whenever an aggregate value type is seen.
    798                         // it's okay for the aggregate expression to have reference type -- cast it to the
     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 
    799784                        // base type to treat the aggregate as the referenced value
    800785                        ast::ptr< ast::Expr > aggrExpr( cand->expr );
    801786                        ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;
    802787                        cand->env.apply( aggrType );
    803 
     788                       
    804789                        if ( aggrType.as< ast::ReferenceType >() ) {
    805790                                aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };
     
    814799
    815800                /// Adds aggregate member interpretations
    816                 void addAggMembers(
    817                         const ast::ReferenceToType * aggrInst, const ast::Expr * expr,
    818                         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 
    819804                ) {
    820805                        for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {
    821806                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );
    822                                 CandidateRef newCand = std::make_shared<Candidate>(
     807                                CandidateRef newCand = std::make_shared<Candidate>( 
    823808                                        cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
    824                                 // add anonymous member interpretations whenever an aggregate value type is seen
     809                                // add anonymous member interpretations whenever an aggregate value type is seen 
    825810                                // as a member expression
    826811                                addAnonConversions( newCand );
     
    830815
    831816                /// Adds tuple member interpretations
    832                 void addTupleMembers(
    833                         const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,
    834                         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 
    835820                ) {
    836821                        if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) {
    837                                 // 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 
    838823                                // length of the tuple to have meaning
    839824                                long long val = constantExpr->intValue();
    840825                                if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    841826                                        addCandidate(
    842                                                 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },
     827                                                cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 
    843828                                                addedCost );
    844829                                }
     
    852837                        if ( funcFinder.candidates.empty() ) return;
    853838
    854                         reason.code = NoMatch;
    855 
    856                         std::vector< CandidateFinder > argCandidates =
     839                        std::vector< CandidateFinder > argCandidates =
    857840                                selfFinder.findSubExprs( untypedExpr->args );
    858 
     841                       
    859842                        // take care of possible tuple assignments
    860843                        // if not tuple assignment, handled as normal function call
     
    894877                                                if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    895878                                                        CandidateRef newFunc{ new Candidate{ *func } };
    896                                                         newFunc->expr =
     879                                                        newFunc->expr = 
    897880                                                                referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    898881                                                        makeFunctionCandidates( newFunc, function, argExpansions, found );
    899882                                                }
    900                                         } else if (
    901                                                 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
     883                                        } else if ( 
     884                                                auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 
    902885                                        ) {
    903886                                                if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) {
    904887                                                        if ( auto function = clz->bound.as< ast::FunctionType >() ) {
    905888                                                                CandidateRef newFunc{ new Candidate{ *func } };
    906                                                                 newFunc->expr =
     889                                                                newFunc->expr = 
    907890                                                                        referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    908891                                                                makeFunctionCandidates( newFunc, function, argExpansions, found );
     
    918901                                std::vector< ExplodedArg > funcE;
    919902                                funcE.reserve( funcFinder.candidates.size() );
    920                                 for ( const CandidateRef & func : funcFinder ) {
     903                                for ( const CandidateRef & func : funcFinder ) { 
    921904                                        funcE.emplace_back( *func, symtab );
    922905                                }
     
    930913                                                        if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    931914                                                                CandidateRef newOp{ new Candidate{ *op} };
    932                                                                 newOp->expr =
     915                                                                newOp->expr = 
    933916                                                                        referenceToRvalueConversion( newOp->expr, newOp->cost );
    934917                                                                makeFunctionCandidates( newOp, function, argExpansions, found );
     
    939922                        }
    940923
    941                         // 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 
    942925                        // candidates
    943926                        if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
     
    951934                                        auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
    952935                                        auto function = pointer->base.strict_as< ast::FunctionType >();
    953 
     936                                       
    954937                                        std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;
    955938                                        std::cerr << "parameters are:" << std::endl;
     
    974957                        promoteCvtCost( winners );
    975958
    976                         // function may return a struct/union value, in which case we need to add candidates
    977                         // for implicit conversions to each of the anonymous members, which must happen after
     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 
    978961                        // `findMinCost`, since anon conversions are never the cheapest
    979962                        for ( const CandidateRef & c : winners ) {
     
    983966
    984967                        if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
    985                                 // 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 
    986969                                // will sometimes succeed when it wouldn't with a target type binding.
    987970                                // For example:
     
    1000983                /// true if expression is an lvalue
    1001984                static bool isLvalue( const ast::Expr * x ) {
    1002                         return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() );
     985                        return x->result && ( x->result->is_lvalue() || x->result.as< ast::ReferenceType >() );
    1003986                }
    1004987
     
    1006989                        CandidateFinder finder{ symtab, tenv };
    1007990                        finder.find( addressExpr->arg );
    1008 
    1009                         if( finder.candidates.empty() ) return;
    1010 
    1011                         reason.code = NoMatch;
    1012 
    1013991                        for ( CandidateRef & r : finder.candidates ) {
    1014992                                if ( ! isLvalue( r->expr ) ) continue;
     
    10311009                        finder.find( castExpr->arg, ResolvMode::withAdjustment() );
    10321010
    1033                         if( !finder.candidates.empty() ) reason.code = NoMatch;
    1034 
    10351011                        CandidateList matches;
    10361012                        for ( CandidateRef & cand : finder.candidates ) {
     
    10401016                                cand->env.extractOpenVars( open );
    10411017
    1042                                 // It is possible that a cast can throw away some values in a multiply-valued
    1043                                 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the
    1044                                 // subexpression results that are cast directly. The candidate is invalid if it
     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 
    10451021                                // has fewer results than there are types to cast to.
    10461022                                int discardedValues = cand->expr->result->size() - toType->size();
     
    10491025                                // unification run for side-effects
    10501026                                unify( toType, cand->expr->result, cand->env, need, have, open, symtab );
    1051                                 Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
    1052                                                 symtab, cand->env );
     1027                                Cost thisCost = castCost( cand->expr->result, toType, symtab, cand->env );
    10531028                                PRINT(
    10541029                                        std::cerr << "working on cast with result: " << toType << std::endl;
     
    10621037                                        // count one safe conversion for each value that is thrown away
    10631038                                        thisCost.incSafe( discardedValues );
    1064                                         CandidateRef newCand = std::make_shared<Candidate>(
    1065                                                 restructureCast( cand->expr, toType, castExpr->isGenerated ),
    1066                                                 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, 
    10671042                                                cand->cost + thisCost );
    10681043                                        inferParameters( newCand, matches );
     
    10821057                        finder.find( castExpr->arg, ResolvMode::withoutPrune() );
    10831058                        for ( CandidateRef & r : finder.candidates ) {
    1084                                 addCandidate(
    1085                                         *r,
     1059                                addCandidate( 
     1060                                        *r, 
    10861061                                        new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
    10871062                        }
     
    10921067                        aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    10931068                        for ( CandidateRef & agg : aggFinder.candidates ) {
    1094                                 // 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 
    10951070                                // base type to treat the aggregate as the referenced value
    10961071                                Cost addedCost = Cost::zero;
     
    10991074                                // find member of the given type
    11001075                                if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {
    1101                                         addAggMembers(
     1076                                        addAggMembers( 
    11021077                                                structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    11031078                                } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {
    1104                                         addAggMembers(
     1079                                        addAggMembers( 
    11051080                                                unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    11061081                                } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {
     
    11171092                        std::vector< ast::SymbolTable::IdData > declList = symtab.lookupId( nameExpr->name );
    11181093                        PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
    1119                         if( declList.empty() ) return;
    1120 
    1121                         reason.code = NoMatch;
    1122 
    11231094                        for ( auto & data : declList ) {
    11241095                                Cost cost = Cost::zero;
     
    11261097
    11271098                                CandidateRef newCand = std::make_shared<Candidate>(
    1128                                         newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
     1099                                        newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 
    11291100                                        cost );
    11301101                                PRINT(
     
    11361107                                        std::cerr << std::endl;
    11371108                                )
    1138                                 newCand->expr = ast::mutate_field(
    1139                                         newCand->expr.get(), &ast::Expr::result,
     1109                                newCand->expr = ast::mutate_field( 
     1110                                        newCand->expr.get(), &ast::Expr::result, 
    11401111                                        renameTyVars( newCand->expr->result ) );
    1141                                 // add anonymous member interpretations whenever an aggregate value type is seen
     1112                                // add anonymous member interpretations whenever an aggregate value type is seen 
    11421113                                // as a name expression
    11431114                                addAnonConversions( newCand );
     
    11491120                        // not sufficient to just pass `variableExpr` here, type might have changed since
    11501121                        // creation
    1151                         addCandidate(
     1122                        addCandidate( 
    11521123                                new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
    11531124                }
     
    11591130                void postvisit( const ast::SizeofExpr * sizeofExpr ) {
    11601131                        if ( sizeofExpr->type ) {
    1161                                 addCandidate(
    1162                                         new ast::SizeofExpr{
    1163                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
     1132                                addCandidate( 
     1133                                        new ast::SizeofExpr{ 
     1134                                                sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 
    11641135                                        tenv );
    11651136                        } else {
     
    11701141                                CandidateList winners = findMinCost( finder.candidates );
    11711142                                if ( winners.size() != 1 ) {
    1172                                         SemanticError(
     1143                                        SemanticError( 
    11731144                                                sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );
    11741145                                }
     
    11831154                void postvisit( const ast::AlignofExpr * alignofExpr ) {
    11841155                        if ( alignofExpr->type ) {
    1185                                 addCandidate(
    1186                                         new ast::AlignofExpr{
    1187                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
     1156                                addCandidate( 
     1157                                        new ast::AlignofExpr{ 
     1158                                                alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 
    11881159                                        tenv );
    11891160                        } else {
     
    11941165                                CandidateList winners = findMinCost( finder.candidates );
    11951166                                if ( winners.size() != 1 ) {
    1196                                         SemanticError(
     1167                                        SemanticError( 
    11971168                                                alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );
    11981169                                }
     
    12011172                                choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    12021173                                choice->cost = Cost::zero;
    1203                                 addCandidate(
     1174                                addCandidate( 
    12041175                                        *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );
    12051176                        }
     
    12141185                        for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {
    12151186                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );
    1216                                 addCandidate(
     1187                                addCandidate( 
    12171188                                        new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );
    12181189                        }
     
    12351206                        finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );
    12361207                        if ( finder2.candidates.empty() ) return;
    1237 
    1238                         reason.code = NoMatch;
    12391208
    12401209                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    12491218
    12501219                                        addCandidate(
    1251                                                 new ast::LogicalExpr{
     1220                                                new ast::LogicalExpr{ 
    12521221                                                        logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
    12531222                                                move( env ), move( open ), move( need ), r1->cost + r2->cost );
     
    12711240                        finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );
    12721241                        if ( finder3.candidates.empty() ) return;
    1273 
    1274                         reason.code = NoMatch;
    12751242
    12761243                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    12891256                                                ast::AssertionSet have;
    12901257
    1291                                                 // unify true and false results, then infer parameters to produce new
     1258                                                // unify true and false results, then infer parameters to produce new 
    12921259                                                // candidates
    12931260                                                ast::ptr< ast::Type > common;
    1294                                                 if (
    1295                                                         unify(
    1296                                                                 r2->expr->result, r3->expr->result, env, need, have, open, symtab,
    1297                                                                 common )
     1261                                                if ( 
     1262                                                        unify( 
     1263                                                                r2->expr->result, r3->expr->result, env, need, have, open, symtab, 
     1264                                                                common ) 
    12981265                                                ) {
    12991266                                                        // generate typed expression
    1300                                                         ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{
     1267                                                        ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 
    13011268                                                                conditionalExpr->location, r1->expr, r2->expr, r3->expr };
    13021269                                                        newExpr->result = common ? common : r2->expr->result;
    13031270                                                        // convert both options to result type
    13041271                                                        Cost cost = r1->cost + r2->cost + r3->cost;
    1305                                                         newExpr->arg2 = computeExpressionConversionCost(
     1272                                                        newExpr->arg2 = computeExpressionConversionCost( 
    13061273                                                                newExpr->arg2, newExpr->result, symtab, env, cost );
    13071274                                                        newExpr->arg3 = computeExpressionConversionCost(
     
    13201287                        ast::TypeEnvironment env{ tenv };
    13211288                        ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
    1322 
     1289                       
    13231290                        CandidateFinder finder2{ symtab, env };
    13241291                        finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
     
    13501317                        finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );
    13511318                        if ( finder2.candidates.empty() ) return;
    1352 
    1353                         reason.code = NoMatch;
    13541319
    13551320                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    13651330
    13661331                                        ast::ptr< ast::Type > common;
    1367                                         if (
    1368                                                 unify(
    1369                                                         r1->expr->result, r2->expr->result, env, need, have, open, symtab,
    1370                                                         common )
     1332                                        if ( 
     1333                                                unify( 
     1334                                                        r1->expr->result, r2->expr->result, env, need, have, open, symtab, 
     1335                                                        common ) 
    13711336                                        ) {
    13721337                                                // generate new expression
    1373                                                 ast::RangeExpr * newExpr =
     1338                                                ast::RangeExpr * newExpr = 
    13741339                                                        new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
    13751340                                                newExpr->result = common ? common : r1->expr->result;
    13761341                                                // add candidate
    13771342                                                CandidateRef newCand = std::make_shared<Candidate>(
    1378                                                         newExpr, move( env ), move( open ), move( need ),
     1343                                                        newExpr, move( env ), move( open ), move( need ), 
    13791344                                                        r1->cost + r2->cost );
    13801345                                                inferParameters( newCand, candidates );
     
    13851350
    13861351                void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
    1387                         std::vector< CandidateFinder > subCandidates =
     1352                        std::vector< CandidateFinder > subCandidates = 
    13881353                                selfFinder.findSubExprs( tupleExpr->exprs );
    13891354                        std::vector< CandidateList > possibilities;
     
    14051370
    14061371                                addCandidate(
    1407                                         new ast::TupleExpr{ tupleExpr->location, move( exprs ) },
     1372                                        new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 
    14081373                                        move( env ), move( open ), move( need ), sumCost( subs ) );
    14091374                        }
     
    14471412                                toType = SymTab::validateType( initExpr->location, toType, symtab );
    14481413                                toType = adjustExprType( toType, tenv, symtab );
    1449                                 // The call to find must occur inside this loop, otherwise polymorphic return
    1450                                 // types are not bound to the initialization type, since return type variables are
    1451                                 // only open for the duration of resolving the UntypedExpr.
     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. 
    14521417                                CandidateFinder finder{ symtab, tenv, toType };
    14531418                                finder.find( initExpr->expr, ResolvMode::withAdjustment() );
    14541419                                for ( CandidateRef & cand : finder.candidates ) {
    1455                                         if(reason.code == NotFound) reason.code = NoMatch;
    1456 
    14571420                                        ast::TypeEnvironment env{ cand->env };
    14581421                                        ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;
     
    14631426                                        )
    14641427
    1465                                         // It is possible that a cast can throw away some values in a multiply-valued
    1466                                         // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of
    1467                                         // the subexpression results that are cast directly. The candidate is invalid
     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 
    14681431                                        // if it has fewer results than there are types to cast to.
    14691432                                        int discardedValues = cand->expr->result->size() - toType->size();
     
    14721435                                        // unification run for side-effects
    14731436                                        unify( toType, cand->expr->result, env, need, have, open, symtab );
    1474                                         Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
    1475                                                         symtab, env );
    1476 
     1437                                        Cost thisCost = castCost( cand->expr->result, toType, symtab, env );
     1438                                       
    14771439                                        if ( thisCost != Cost::infinity ) {
    14781440                                                // count one safe conversion for each value that is thrown away
    14791441                                                thisCost.incSafe( discardedValues );
    1480                                                 CandidateRef newCand = std::make_shared<Candidate>(
    1481                                                         new ast::InitExpr{
    1482                                                                 initExpr->location, restructureCast( cand->expr, toType ),
    1483                                                                 initAlt.designation },
     1442                                                CandidateRef newCand = std::make_shared<Candidate>( 
     1443                                                        new ast::InitExpr{ 
     1444                                                                initExpr->location, restructureCast( cand->expr, toType ), 
     1445                                                                initAlt.designation }, 
    14841446                                                        copy( cand->env ), move( open ), move( need ), cand->cost, thisCost );
    14851447                                                inferParameters( newCand, matches );
     
    15071469        };
    15081470
    1509         /// 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 
    15101472        /// return type. Skips ambiguous candidates.
    15111473        CandidateList pruneCandidates( CandidateList & candidates ) {
     
    15241486                        {
    15251487                                ast::ptr< ast::Type > newType = candidate->expr->result;
    1526                                 assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());
    15271488                                candidate->env.apply( newType );
    15281489                                mangleName = Mangle::mangle( newType );
     
    15331494                                if ( candidate->cost < found->second.candidate->cost ) {
    15341495                                        PRINT(
    1535                                                 std::cerr << "cost " << candidate->cost << " beats "
     1496                                                std::cerr << "cost " << candidate->cost << " beats " 
    15361497                                                        << found->second.candidate->cost << std::endl;
    15371498                                        )
     
    15391500                                        found->second = PruneStruct{ candidate };
    15401501                                } else if ( candidate->cost == found->second.candidate->cost ) {
    1541                                         // if one of the candidates contains a deleted identifier, can pick the other,
    1542                                         // since deleted expressions should not be ambiguous if there is another option
     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 
    15431504                                        // that is at least as good
    15441505                                        if ( findDeletedExpr( candidate->expr ) ) {
     
    15541515                                } else {
    15551516                                        PRINT(
    1556                                                 std::cerr << "cost " << candidate->cost << " loses to "
     1517                                                std::cerr << "cost " << candidate->cost << " loses to " 
    15571518                                                        << found->second.candidate->cost << std::endl;
    15581519                                        )
     
    15691530
    15701531                        CandidateRef cand = target.second.candidate;
    1571 
     1532                       
    15721533                        ast::ptr< ast::Type > newResult = cand->expr->result;
    15731534                        cand->env.applyFree( newResult );
    15741535                        cand->expr = ast::mutate_field(
    15751536                                cand->expr.get(), &ast::Expr::result, move( newResult ) );
    1576 
     1537                       
    15771538                        out.emplace_back( cand );
    15781539                }
     
    15881549
    15891550        if ( mode.failFast && candidates.empty() ) {
    1590                 switch(finder.pass.reason.code) {
    1591                 case Finder::NotFound:
    1592                         { SemanticError( expr, "No alternatives for expression " ); break; }
    1593                 case Finder::NoMatch:
    1594                         { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; }
    1595                 case Finder::ArgsToFew:
    1596                 case Finder::ArgsToMany:
    1597                 case Finder::RetsToFew:
    1598                 case Finder::RetsToMany:
    1599                 case Finder::NoReason:
    1600                 default:
    1601                         { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); }
    1602                 }
     1551                SemanticError( expr, "No reasonable alternatives for expression " );
    16031552        }
    16041553
     
    16091558                std::vector< std::string > errors;
    16101559                for ( CandidateRef & candidate : candidates ) {
    1611                         satisfyAssertions( candidate, localSyms, satisfied, errors );
     1560                        satisfyAssertions( candidate, symtab, satisfied, errors );
    16121561                }
    16131562
     
    16341583
    16351584                CandidateList pruned = pruneCandidates( candidates );
    1636 
     1585               
    16371586                if ( mode.failFast && pruned.empty() ) {
    16381587                        std::ostringstream stream;
     
    16531602                )
    16541603                PRINT(
    1655                         std::cerr << "there are " << candidates.size() << " alternatives after elimination"
     1604                        std::cerr << "there are " << candidates.size() << " alternatives after elimination" 
    16561605                                << std::endl;
    16571606                )
    16581607        }
    16591608
    1660         // 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 
    16611610        // adjusted
    16621611        if ( mode.adjust ) {
    16631612                for ( CandidateRef & r : candidates ) {
    1664                         r->expr = ast::mutate_field(
    1665                                 r->expr.get(), &ast::Expr::result,
    1666                                 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 ) );
    16671616                }
    16681617        }
     
    16761625}
    16771626
    1678 std::vector< CandidateFinder > CandidateFinder::findSubExprs(
    1679         const std::vector< ast::ptr< ast::Expr > > & xs
     1627std::vector< CandidateFinder > CandidateFinder::findSubExprs( 
     1628        const std::vector< ast::ptr< ast::Expr > > & xs 
    16801629) {
    16811630        std::vector< CandidateFinder > out;
    16821631
    16831632        for ( const auto & x : xs ) {
    1684                 out.emplace_back( localSyms, env );
     1633                out.emplace_back( symtab, env );
    16851634                out.back().find( x, ResolvMode::withAdjustment() );
    1686 
     1635               
    16871636                PRINT(
    16881637                        std::cerr << "findSubExprs" << std::endl;
  • src/ResolvExpr/CandidateFinder.hpp

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    r7030dab r057298e  
    2121
    2222#include "AST/Decl.hpp"
    23 #include "AST/Eval.hpp"
    2423#include "AST/Expr.hpp"
    2524#include "AST/Init.hpp"
     
    266265                }
    267266
    268                 ast::ptr< ast::Expr > begin, end;
    269                 std::string cmp, update;
     267                ast::ptr< ast::Expr > begin, end, cmp, update;
    270268
    271269                if ( forward ) {
     
    273271                        begin = ast::ConstantExpr::from_int( loc, 0 );
    274272                        end = array->dimension;
    275                         cmp = "?<?";
    276                         update = "++?";
     273                        cmp = new ast::NameExpr{ loc, "?<?" };
     274                        update = new ast::NameExpr{ loc, "++?" };
    277275                } else {
    278276                        // generate: for ( int i = N-1; i >= 0; --i )
    279                         begin = ast::call(
    280                                 loc, "?-?", array->dimension, ast::ConstantExpr::from_int( loc, 1 ) );
     277                        begin = new ast::UntypedExpr{
     278                                loc, new ast::NameExpr{ loc, "?-?" },
     279                                { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } };
    281280                        end = ast::ConstantExpr::from_int( loc, 0 );
    282                         cmp = "?>=?";
    283                         update = "--?";
     281                        cmp = new ast::NameExpr{ loc, "?>=?" };
     282                        update = new ast::NameExpr{ loc, "--?" };
    284283                }
    285284
     
    287286                        loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },
    288287                        new ast::SingleInit{ loc, begin } };
    289                 ast::ptr< ast::Expr > indexVar = new ast::VariableExpr{ loc, index };
    290                
    291                 ast::ptr< ast::Expr > cond = ast::call( loc, cmp, indexVar, end );
    292                
    293                 ast::ptr< ast::Expr > inc = ast::call( loc, update, indexVar );
    294                
    295                 ast::ptr< ast::Expr > dstIndex = ast::call( loc, "?[?]", dstParam, indexVar );
     288               
     289                ast::ptr< ast::Expr > cond = new ast::UntypedExpr{
     290                        loc, cmp, { new ast::VariableExpr{ loc, index }, end } };
     291               
     292                ast::ptr< ast::Expr > inc = new ast::UntypedExpr{
     293                        loc, update, { new ast::VariableExpr{ loc, index } } };
     294               
     295                ast::ptr< ast::Expr > dstIndex = new ast::UntypedExpr{
     296                        loc, new ast::NameExpr{ loc, "?[?]" },
     297                        { dstParam, new ast::VariableExpr{ loc, index } } };
    296298               
    297299                // srcParam must keep track of the array indices to build the source parameter and/or
    298300                // array list initializer
    299                 srcParam.addArrayIndex( indexVar, array->dimension );
     301                srcParam.addArrayIndex( new ast::VariableExpr{ loc, index }, array->dimension );
    300302
    301303                // for stmt's body, eventually containing call
     
    383385                if ( isUnnamedBitfield( obj ) ) return {};
    384386
    385                 ast::ptr< ast::Type > addCast;
     387                ast::ptr< ast::Type > addCast = nullptr;
    386388                if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
    387389                        assert( dstParam->result );
  • src/SynTree/Statement.h

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

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

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

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

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

    r7030dab r057298e  
    3131using namespace std;
    3232
    33 #include "AST/Convert.hpp"
     33
    3434#include "CompilationState.h"
    3535#include "../config.h"                      // for CFA_LIBDIR
     
    339339                } // if
    340340
    341                 // PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
    342                 {
    343                         auto transUnit = convert( move( translationUnit ) );
    344                         PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
    345                         translationUnit = convert( move( transUnit ) );
    346                 }
    347 
     341                PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
    348342                if ( exprp ) {
    349343                        dump( translationUnit );
Note: See TracChangeset for help on using the changeset viewer.