Changes in / [fb0ae06:dab09ad]


Ignore:
Files:
6 deleted
68 edited

Legend:

Unmodified
Added
Removed
  • configure.ac

    rfb0ae06 rdab09ad  
    2424#Trasforming cc1 will break compilation
    2525M4CFA_PROGRAM_NAME
    26 
    27 #==============================================================================
    28 # New AST toggling support
    29 AH_TEMPLATE([CFA_USE_NEW_AST],[Sets whether or not to use the new-ast, this is adefault value and can be overrided by --old-ast and --new-ast])
    30 AC_ARG_ENABLE(new-ast,
    31         [  --enable-new-ast     whether or not to use new ast as the default AST algorithm],
    32         [case "${enableval}" in
    33                 yes) newast=true ;;
    34                 no)  newast=false ;;
    35                 *) AC_MSG_ERROR([bad value ${enableval} for --enable-new-ast]) ;;
    36         esac],[newast=false])
    37 AC_DEFINE_UNQUOTED([CFA_USE_NEW_AST], $newast)
    3826
    3927#==============================================================================
  • libcfa/src/Makefile.am

    rfb0ae06 rdab09ad  
    4444
    4545headers = common.hfa fstream.hfa heap.hfa iostream.hfa iterator.hfa limits.hfa rational.hfa \
    46                 time.hfa stdlib.hfa parseargs.hfa \
     46                time.hfa stdlib.hfa memory.hfa parseargs.hfa \
    4747                containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/vector.hfa
    4848
  • libcfa/src/concurrency/ready_queue.cfa

    rfb0ae06 rdab09ad  
    419419        // Actually pop the list
    420420        struct $thread * thrd;
    421         thrd = pop(lane);
     421        bool emptied;
     422        [thrd, emptied] = pop(lane);
    422423
    423424        /* paranoid */ verify(thrd);
     
    456457                        if(head(lane)->link.next == thrd) {
    457458                                $thread * pthrd;
    458                                 pthrd = pop(lane);
     459                                bool emptied;
     460                                [pthrd, emptied] = pop(lane);
    459461
    460462                                /* paranoid */ verify( pthrd == thrd );
     
    606608                        while(!is_empty(lanes.data[idx])) {
    607609                                struct $thread * thrd;
    608                                 thrd = pop(lanes.data[idx]);
     610                                __attribute__((unused)) bool _;
     611                                [thrd, _] = pop(lanes.data[idx]);
    609612
    610613                                push(cltr, thrd);
  • libcfa/src/concurrency/ready_subqueue.hfa

    rfb0ae06 rdab09ad  
    144144// returns popped
    145145// returns true of lane was empty before push, false otherwise
    146 $thread * pop(__intrusive_lane_t & this) {
     146[$thread *, bool] pop(__intrusive_lane_t & this) {
    147147        /* paranoid */ verify(this.lock);
    148148        /* paranoid */ verify(this.before.link.ts != 0ul);
     
    162162        head->link.next = next;
    163163        next->link.prev = head;
    164         node->link.next = 0p;
    165         node->link.prev = 0p;
     164        node->link.[next, prev] = 0p;
    166165
    167166        // Update head time stamp
     
    181180                /* paranoid */ verify(tail(this)->link.prev == head(this));
    182181                /* paranoid */ verify(head(this)->link.next == tail(this));
    183                 return node;
     182                return [node, true];
    184183        }
    185184        else {
     
    188187                /* paranoid */ verify(head(this)->link.next != tail(this));
    189188                /* paranoid */ verify(this.before.link.ts != 0);
    190                 return node;
     189                return [node, false];
    191190        }
    192191}
  • src/AST/Attribute.hpp

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    2020
    2121#include "AST/Attribute.hpp"
    22 #include "AST/Copy.hpp"
    2322#include "AST/Decl.hpp"
    2423#include "AST/Expr.hpp"
     
    588587                assert( tgtResnSlots.empty() );
    589588
    590                 if ( srcInferred.data.inferParams ) {
     589                if ( srcInferred.mode == ast::Expr::InferUnion::Params ) {
    591590                        const ast::InferredParams &srcParams = srcInferred.inferParams();
    592591                        for (auto & srcParam : srcParams) {
     
    594593                                        srcParam.second.decl,
    595594                                        get<Declaration>().accept1(srcParam.second.declptr),
    596                                         get<Type>().accept1(srcParam.second.actualType)->clone(),
    597                                         get<Type>().accept1(srcParam.second.formalType)->clone(),
    598                                         get<Expression>().accept1(srcParam.second.expr)->clone()
     595                                        get<Type>().accept1(srcParam.second.actualType),
     596                                        get<Type>().accept1(srcParam.second.formalType),
     597                                        get<Expression>().accept1(srcParam.second.expr)
    599598                                ));
    600599                                assert(res.second);
    601600                        }
    602                 }
    603                 if ( srcInferred.data.resnSlots ) {
     601                } else if ( srcInferred.mode == ast::Expr::InferUnion::Slots  ) {
    604602                        const ast::ResnSlots &srcSlots = srcInferred.resnSlots();
    605603                        for (auto srcSlot : srcSlots) {
     
    622620
    623621                tgt->result = get<Type>().accept1(src->result);
    624                 // Unconditionally use a clone of the result type.
    625                 // We know this will leak some objects: much of the immediate conversion result.
    626                 // In some cases, using the conversion result directly gives unintended object sharing.
    627                 // A parameter (ObjectDecl, a child of a FunctionType) is shared by the weak-ref cache.
    628                 // But tgt->result must be fully owned privately by tgt.
    629                 // Applying these conservative copies here means
    630                 // - weak references point at the declaration's copy, not these expr.result copies (good)
    631                 // - we copy more objects than really needed (bad, tolerated)
    632                 if (tgt->result) {
    633                         tgt->result = tgt->result->clone();
    634                 }
    635622                return visitBaseExpr_skipResultType(src, tgt);
    636623        }
     
    992979
    993980        const ast::Expr * visit( const ast::StmtExpr * node ) override final {
    994                 auto stmts = node->stmts;
    995                 // disable sharing between multiple StmtExprs explicitly.
    996                 if (inCache(stmts)) {
    997                         stmts = ast::deepCopy(stmts.get());
    998                 }
    999981                auto rslt = new StmtExpr(
    1000                         get<CompoundStmt>().accept1(stmts)
     982                        get<CompoundStmt>().accept1(node->stmts)
    1001983                );
    1002984
     
    20041986
    20051987                assert( oldInferParams.empty() || oldResnSlots.empty() );
    2006                 // assert( newInferred.mode == ast::Expr::InferUnion::Empty );
     1988                assert( newInferred.mode == ast::Expr::InferUnion::Empty );
    20071989
    20081990                if ( !oldInferParams.empty() ) {
     
    21352117                                old->location,
    21362118                                GET_ACCEPT_1(member, DeclWithType),
    2137                                 GET_ACCEPT_1(aggregate, Expr),
    2138                                 ast::MemberExpr::NoOpConstructionChosen
     2119                                GET_ACCEPT_1(aggregate, Expr)
    21392120                        )
    21402121                );
  • src/AST/Decl.cpp

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    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, TypeDecl::Kind k, bool s, const Type * i = nullptr )
    194         : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeDecl::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

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    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;
     
    4542struct ParamEntry {
    4643        UniqueId decl;
    47         readonly<Decl> declptr;
     44        ptr<Decl> declptr;
    4845        ptr<Type> actualType;
    4946        ptr<Type> formalType;
     
    6562class Expr : public ParseNode {
    6663public:
    67         /*
    68          * NOTE: the union approach is incorrect until the case of
    69          * partial resolution in InferMatcher is eliminated.
    70          * it is reverted to allow unresolved and resolved parameters
    71          * to coexist in an expression node.
    72          */
     64        /// Saves space (~16 bytes) by combining ResnSlots and InferredParams
    7365        struct InferUnion {
    74                 // mode is now unused
    7566                enum { Empty, Slots, Params } mode;
    76                 struct data_t {
    77                         // char def;
    78                         ResnSlots * resnSlots;
    79                         InferredParams * inferParams;
    80 
    81                         data_t(): resnSlots(nullptr), inferParams(nullptr) {}
    82                         data_t(const data_t &other) = delete;
    83                         ~data_t() {
    84                                 delete resnSlots;
    85                                 delete inferParams;
    86                         }
     67                union data_t {
     68                        char def;
     69                        ResnSlots resnSlots;
     70                        InferredParams inferParams;
     71
     72                        data_t() : def('\0') {}
     73                        ~data_t() {}
    8774                } data;
    8875
    8976                /// initializes from other InferUnion
    9077                void init_from( const InferUnion& o ) {
    91                         if (o.data.resnSlots) {
    92                                 data.resnSlots = new ResnSlots(*o.data.resnSlots);
    93                         }
    94                         if (o.data.inferParams) {
    95                                 data.inferParams = new InferredParams(*o.data.inferParams);
     78                        switch ( o.mode ) {
     79                        case Empty:  return;
     80                        case Slots:  new(&data.resnSlots) ResnSlots{ o.data.resnSlots }; return;
     81                        case Params: new(&data.inferParams) InferredParams{ o.data.inferParams }; return;
    9682                        }
    9783                }
     
    9985                /// initializes from other InferUnion (move semantics)
    10086                void init_from( InferUnion&& o ) {
    101                         data.resnSlots = o.data.resnSlots;
    102                         data.inferParams = o.data.inferParams;
    103                         o.data.resnSlots = nullptr;
    104                         o.data.inferParams = nullptr;
     87                        switch ( o.mode ) {
     88                        case Empty:  return;
     89                        case Slots:  new(&data.resnSlots) ResnSlots{ std::move(o.data.resnSlots) }; return;
     90                        case Params:
     91                                new(&data.inferParams) InferredParams{ std::move(o.data.inferParams) }; return;
     92                        }
     93                }
     94
     95                /// clears variant fields
     96                void reset() {
     97                        switch( mode ) {
     98                        case Empty:  return;
     99                        case Slots:  data.resnSlots.~ResnSlots(); return;
     100                        case Params: data.inferParams.~InferredParams(); return;
     101                        }
    105102                }
    106103
     
    110107                InferUnion& operator= ( const InferUnion& ) = delete;
    111108                InferUnion& operator= ( InferUnion&& ) = delete;
    112 
    113                 bool hasSlots() const { return data.resnSlots; }
     109                ~InferUnion() { reset(); }
    114110
    115111                ResnSlots& resnSlots() {
    116                         if (!data.resnSlots) {
    117                                 data.resnSlots = new ResnSlots();
     112                        switch (mode) {
     113                        case Empty: new(&data.resnSlots) ResnSlots{}; mode = Slots; // fallthrough
     114                        case Slots: return data.resnSlots;
     115                        case Params: assertf(false, "Cannot return to resnSlots from Params"); abort();
    118116                        }
    119                         return *data.resnSlots;
     117                        assertf(false, "unreachable");
    120118                }
    121119
    122120                const ResnSlots& resnSlots() const {
    123                         if (data.resnSlots) {
    124                                 return *data.resnSlots;
     121                        if (mode == Slots) {
     122                                return data.resnSlots;
    125123                        }
    126124                        assertf(false, "Mode was not already resnSlots");
     
    129127
    130128                InferredParams& inferParams() {
    131                         if (!data.inferParams) {
    132                                 data.inferParams = new InferredParams();
     129                        switch (mode) {
     130                        case Slots: data.resnSlots.~ResnSlots(); // fallthrough
     131                        case Empty: new(&data.inferParams) InferredParams{}; mode = Params; // fallthrough
     132                        case Params: return data.inferParams;
    133133                        }
    134                         return *data.inferParams;
     134                        assertf(false, "unreachable");
    135135                }
    136136
    137137                const InferredParams& inferParams() const {
    138                         if (data.inferParams) {
    139                                 return *data.inferParams;
     138                        if (mode == Params) {
     139                                return data.inferParams;
    140140                        }
    141141                        assertf(false, "Mode was not already Params");
     
    143143                }
    144144
    145                 void set_inferParams( InferredParams * ps ) {
    146                         delete data.resnSlots;
    147                         data.resnSlots = nullptr;
    148                         delete data.inferParams;
    149                         data.inferParams = ps;
     145                void set_inferParams( InferredParams && ps ) {
     146                        switch(mode) {
     147                        case Slots:
     148                                data.resnSlots.~ResnSlots();
     149                                // fallthrough
     150                        case Empty:
     151                                new(&data.inferParams) InferredParams{ std::move( ps ) };
     152                                mode = Params;
     153                                break;
     154                        case Params:
     155                                data.inferParams = std::move( ps );
     156                                break;
     157                        }
    150158                }
    151159
     
    153161                /// and the other is in `Params`.
    154162                void splice( InferUnion && o ) {
    155                         if (o.data.resnSlots) {
    156                                 if (data.resnSlots) {
    157                                         data.resnSlots->insert(
    158                                                 data.resnSlots->end(), o.data.resnSlots->begin(), o.data.resnSlots->end() );
    159                                         delete o.data.resnSlots;
     163                        if ( o.mode == Empty ) return;
     164                        if ( mode == Empty ) { init_from( o ); return; }
     165                        assert( mode == o.mode && "attempt to splice incompatible InferUnion" );
     166
     167                        if ( mode == Slots ){
     168                                data.resnSlots.insert(
     169                                        data.resnSlots.end(), o.data.resnSlots.begin(), o.data.resnSlots.end() );
     170                        } else if ( mode == Params ) {
     171                                for ( const auto & p : o.data.inferParams ) {
     172                                        data.inferParams[p.first] = std::move(p.second);
    160173                                }
    161                                 else {
    162                                         data.resnSlots = o.data.resnSlots;
    163                                 }
    164                                 o.data.resnSlots = nullptr;
    165                         }
    166 
    167                         if (o.data.inferParams) {
    168                                 if (data.inferParams) {
    169                                         for ( const auto & p : *o.data.inferParams ) {
    170                                                 (*data.inferParams)[p.first] = std::move(p.second);
    171                                         }
    172                                         delete o.data.inferParams;
    173                                 }
    174                                 else {
    175                                         data.inferParams = o.data.inferParams;
    176                                 }
    177                                 o.data.inferParams = nullptr;
    178                         }
     174                        } else assertf(false, "invalid mode");
    179175                }
    180176        };
     
    189185
    190186        Expr * set_extension( bool ex ) { extension = ex; return this; }
    191         virtual bool get_lvalue() const;
    192187
    193188        virtual const Expr * accept( Visitor & v ) const override = 0;
     
    206201        ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} );
    207202
    208         bool get_lvalue() const final;
    209 
    210203        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    211204private:
     
    222215        UntypedExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} )
    223216        : Expr( loc ), func( f ), args( std::move(as) ) {}
    224 
    225         bool get_lvalue() const final;
    226217
    227218        /// Creates a new dereference expression
     
    300291        CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {}
    301292
    302         bool get_lvalue() const final;
    303 
    304293        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    305294private:
     
    349338        : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); }
    350339
    351         bool get_lvalue() const final;
    352 
    353340        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    354341private:
     
    365352        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg );
    366353
    367         bool get_lvalue() const final;
    368 
    369354        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    370355private:
    371356        MemberExpr * clone() const override { return new MemberExpr{ *this }; }
    372357        MUTATE_FRIEND
    373 
    374         // Custructor overload meant only for AST conversion
    375         enum NoOpConstruction { NoOpConstructionChosen };
    376         MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
    377             NoOpConstruction overloadSelector );
    378         friend class ::ConverterOldToNew;
    379         friend class ::ConverterNewToOld;
    380358};
    381359
     
    387365        VariableExpr( const CodeLocation & loc );
    388366        VariableExpr( const CodeLocation & loc, const DeclWithType * v );
    389 
    390         bool get_lvalue() const final;
    391367
    392368        /// generates a function pointer for a given function
     
    556532
    557533        CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
    558         : Expr( loc ), arg1( a1 ), arg2( a2 ) {
    559                 this->result = a2->result;
    560         }
    561 
    562         bool get_lvalue() const final;
     534        : Expr( loc ), arg1( a1 ), arg2( a2 ) {}
    563535
    564536        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    633605        CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i );
    634606
    635         bool get_lvalue() const final;
    636 
    637607        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    638608private:
     
    690660
    691661        TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i );
    692 
    693         bool get_lvalue() const final;
    694662
    695663        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Fwd.hpp

    rfb0ae06 rdab09ad  
    1010// Created On       : Wed May  8 16:05:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Jul 23 14:15:00 2020
    13 // Update Count     : 2
     12// Last Modified On : Mon Jun 24 09:48:00 2019
     13// Update Count     : 1
    1414//
    1515
     
    108108class FunctionType;
    109109class ReferenceToType;
    110 template<typename decl_t> class SueInstType;
    111 using StructInstType = SueInstType<StructDecl>;
    112 using UnionInstType = SueInstType<UnionDecl>;
    113 using EnumInstType = SueInstType<EnumDecl>;
     110class StructInstType;
     111class UnionInstType;
     112class EnumInstType;
    114113class TraitInstType;
    115114class TypeInstType;
  • src/AST/GenericSubstitution.cpp

    rfb0ae06 rdab09ad  
    6262        Pass<GenericSubstitutionBuilder> builder;
    6363        maybe_accept( ty, builder );
    64         return std::move(builder.core.sub);
     64        return std::move(builder.pass.sub);
    6565}
    6666
  • src/AST/Init.hpp

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    99// Author           : Thierry Delisle
    1010// Created On       : Thu May 16 14:16:00 2019
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jun  5 10:21:00 2020
    13 // Update Count     : 1
     11// Last Modified By :
     12// Last Modified On :
     13// Update Count     :
    1414//
    1515
     
    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 [[noreturn]] static inline void strict_fail(const ast::Node * node) {
    46         assertf(node, "strict_as had nullptr input.");
    47         const ast::ParseNode * parse = dynamic_cast<const ast::ParseNode *>( node );
    48         if ( nullptr == parse ) {
    49                 assertf(nullptr, "%s (no location)", toString(node).c_str());
    50         } else if ( parse->location.isUnset() ) {
    51                 assertf(nullptr, "%s (unset location)", toString(node).c_str());
    52         } else {
    53                 assertf(nullptr, "%s (at %s:%d)", toString(node).c_str(),
    54                         parse->location.filename.c_str(), parse->location.first_line);
    55         }
    56 }
    57 
    58 template< typename node_t, enum ast::Node::ref_type ref_t >
    59 void ast::ptr_base<node_t, ref_t>::_strict_fail() const {
    60         strict_fail(node);
    61 }
    62 
    63 template< typename node_t, enum ast::Node::ref_type ref_t >
    64 void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) {
    65         node->increment(ref_t);
    66         _trap( node );
    67 }
    68 
    69 template< typename node_t, enum ast::Node::ref_type ref_t >
    70 void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node, bool do_delete ) {
    71         _trap( node );
    72         node->decrement( ref_t, do_delete );
    73 }
    74 
    75 template< typename node_t, enum ast::Node::ref_type ref_t >
    76 void ast::ptr_base<node_t, ref_t>::_check() const {
    77         // if(node) assert(node->was_ever_strong == false || node->strong_count > 0);
    78 }
     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); }
    7939
    8040template< typename node_t, enum ast::Node::ref_type ref_t >
  • src/AST/Node.hpp

    rfb0ae06 rdab09ad  
    1010// Created On       : Wed May 8 10:27:04 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jun 5 9:47:00 2020
    13 // Update Count     : 6
     12// Last Modified On : Mon Jun  3 13:26:00 2019
     13// Update Count     : 5
    1414//
    1515
     
    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>
    243223        const o_node_t * as() const { _check(); return dynamic_cast<const o_node_t *>(node); }
    244224
    245         /// Wrapper that makes sure dynamic_cast returns non-null.
     225        /// wrapper for convenient access to strict_dynamic_cast
    246226        template<typename o_node_t>
    247         const o_node_t * strict_as() const {
    248                 if (const o_node_t * ret = as<o_node_t>()) return ret;
    249                 _strict_fail();
    250         }
    251 
    252         /// Wrapper that makes sure dynamic_cast does not fail.
    253         template<typename o_node_t, decltype(nullptr) null>
    254         const o_node_t * strict_as() const { return node ? strict_as<o_node_t>() : nullptr; }
     227        const o_node_t * strict_as() const { _check(); return strict_dynamic_cast<const o_node_t *>(node); }
    255228
    256229        /// Returns a mutable version of the pointer in this node.
     
    271244
    272245        void _inc( const node_t * other );
    273         void _dec( const node_t * other, bool do_delete = true );
     246        void _dec( const node_t * other );
    274247        void _check() const;
    275         void _strict_fail() const __attribute__((noreturn));
    276248
    277249        const node_t * node;
  • src/AST/Pass.hpp

    rfb0ae06 rdab09ad  
    88//
    99// Author           : Thierry Delisle
    10 // Created On       : Thu May 09 15:37:05 2019
     10// Created On       : Thu May 09 15::37::05 2019
    1111// Last Modified By :
    1212// Last Modified On :
     
    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//-------------------------------------------------------------------------------------------------
    68 template< typename core_t >
     65template< typename pass_t >
    6966class Pass final : public ast::Visitor {
    7067public:
    71         using core_type = core_t;
    72         using type = Pass<core_t>;
    73 
    7468        /// Forward any arguments to the pass constructor
    7569        /// Propagate 'this' if necessary
    7670        template< typename... Args >
    7771        Pass( Args &&... args)
    78                 : core( std::forward<Args>( args )... )
     72                : pass( std::forward<Args>( args )... )
    7973        {
    8074                // After the pass is constructed, check if it wants the have a pointer to the wrapping visitor
    81                 type * const * visitor = __pass::visitor(core, 0);
     75                typedef Pass<pass_t> this_t;
     76                this_t * const * visitor = __pass::visitor(pass, 0);
    8277                if(visitor) {
    83                         *const_cast<type **>( visitor ) = this;
     78                        *const_cast<this_t **>( visitor ) = this;
    8479                }
    8580        }
     
    8782        virtual ~Pass() = default;
    8883
    89         /// Construct and run a pass on a translation unit.
    90         template< typename... Args >
    91         static void run( std::list< ptr<Decl> > & decls, Args &&... args ) {
    92                 Pass<core_t> visitor( std::forward<Args>( args )... );
    93                 accept_all( decls, visitor );
    94         }
    95 
    9684        /// Storage for the actual pass
    97         core_t core;
     85        pass_t pass;
    9886
    9987        /// Visit function declarations
     
    191179        const ast::TypeSubstitution * visit( const ast::TypeSubstitution     * ) override final;
    192180
    193         template<typename core_type>
    194         friend void accept_all( std::list< ptr<Decl> > & decls, Pass<core_type>& visitor );
     181        template<typename pass_type>
     182        friend void accept_all( std::list< ptr<Decl> > & decls, Pass<pass_type>& visitor );
    195183private:
    196184
    197         bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children(core, 0); return ptr ? *ptr : true; }
     185        bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children(pass, 0); return ptr ? *ptr : true; }
    198186
    199187private:
     
    214202        container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
    215203
    216         /// Mutate forall-list, accounting for presence of type substitution map
    217         template<typename node_t>
    218         void mutate_forall( const node_t *& );
    219 
    220204public:
    221205        /// Logic to call the accept and mutate the parent if needed, delegates call to accept
     
    226210        /// Internal RAII guard for symbol table features
    227211        struct guard_symtab {
    228                 guard_symtab( Pass<core_t> & pass ): pass( pass ) { __pass::symtab::enter(pass.core, 0); }
    229                 ~guard_symtab()                                   { __pass::symtab::leave(pass.core, 0); }
    230                 Pass<core_t> & pass;
     212                guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass, 0); }
     213                ~guard_symtab()                                   { __pass::symtab::leave(pass, 0); }
     214                Pass<pass_t> & pass;
    231215        };
    232216
    233217        /// Internal RAII guard for scope features
    234218        struct guard_scope {
    235                 guard_scope( Pass<core_t> & pass ): pass( pass ) { __pass::scope::enter(pass.core, 0); }
    236                 ~guard_scope()                                   { __pass::scope::leave(pass.core, 0); }
    237                 Pass<core_t> & pass;
    238         };
    239 
    240         /// Internal RAII guard for forall substitutions
    241         struct guard_forall_subs {
    242                 guard_forall_subs( Pass<core_t> & pass, const ParameterizedType * type )
    243                 : pass( pass ), type( type ) { __pass::forall::enter(pass.core, 0, type ); }
    244                 ~guard_forall_subs()         { __pass::forall::leave(pass.core, 0, type ); }
    245                 Pass<core_t> & pass;
    246                 const ParameterizedType * type;
     219                guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass, 0); }
     220                ~guard_scope()                                   { __pass::scope::leave(pass, 0); }
     221                Pass<pass_t> & pass;
    247222        };
    248223
     
    252227
    253228/// Apply a pass to an entire translation unit
    254 template<typename core_t>
    255 void accept_all( std::list< ast::ptr<ast::Decl> > &, ast::Pass<core_t> & visitor );
     229template<typename pass_t>
     230void accept_all( std::list< ast::ptr<ast::Decl> > &, ast::Pass<pass_t> & visitor );
    256231
    257232//-------------------------------------------------------------------------------------------------
     
    293268        };
    294269
    295         template< typename core_t>
    296         friend auto __pass::at_cleanup( core_t & core, int ) -> decltype( &core.at_cleanup );
     270        template< typename pass_t>
     271        friend auto __pass::at_cleanup( pass_t & pass, int ) -> decltype( &pass.at_cleanup );
    297272public:
    298273
     
    330305
    331306/// Used to get a pointer to the pass with its wrapped type
    332 template<typename core_t>
     307template<typename pass_t>
    333308struct WithVisitorRef {
    334         Pass<core_t> * const visitor = nullptr;
     309        Pass<pass_t> * const visitor = nullptr;
    335310};
    336311
     
    339314        SymbolTable symtab;
    340315};
    341 
    342 /// Use when the templated visitor needs to keep TypeInstType instances properly linked to TypeDecl
    343 struct WithForallSubstitutor {
    344         ForallSubstitutionTable subs;
    345 };
    346 
    347316}
    348317
     
    352321extern struct PassVisitorStats {
    353322        size_t depth = 0;
    354         Stats::Counters::MaxCounter<double> * max;
    355         Stats::Counters::AverageCounter<double> * avg;
     323        Stats::Counters::MaxCounter<double> * max = nullptr;
     324        Stats::Counters::AverageCounter<double> * avg = nullptr;
    356325} pass_visitor_stats;
    357326}
  • src/AST/Pass.impl.hpp

    rfb0ae06 rdab09ad  
    2525        using namespace ast; \
    2626        /* back-up the visit children */ \
    27         __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(core, 0) ); \
     27        __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(pass, 0) ); \
    2828        /* setup the scope for passes that want to run code at exit */ \
    29         __attribute__((unused)) ast::__pass::guard_value          guard2( ast::__pass::at_cleanup    (core, 0) ); \
    30         /* begin tracing memory allocation if requested by this pass */ \
    31         __pass::beginTrace( core, 0 ); \
     29        __attribute__((unused)) ast::__pass::guard_value          guard2( ast::__pass::at_cleanup    (pass, 0) ); \
    3230        /* call the implementation of the previsit of this pass */ \
    33         __pass::previsit( core, node, 0 );
     31        __pass::previsit( pass, node, 0 );
    3432
    3533#define VISIT( code... ) \
     
    4240#define VISIT_END( type, node ) \
    4341        /* call the implementation of the postvisit of this pass */ \
    44         auto __return = __pass::postvisit( core, node, 0 ); \
     42        auto __return = __pass::postvisit( pass, node, 0 ); \
    4543        assertf(__return, "post visit should never return null"); \
    46         /* end tracing memory allocation if requested by this pass */ \
    47         __pass::endTrace( core, 0 ); \
    4844        return __return;
    4945
     
    123119        }
    124120
    125         template< typename core_t >
     121        template< typename pass_t >
    126122        template< typename node_t >
    127         auto ast::Pass< core_t >::call_accept( const node_t * node )
     123        auto ast::Pass< pass_t >::call_accept( const node_t * node )
    128124                -> typename std::enable_if<
    129125                                !std::is_base_of<ast::Expr, node_t>::value &&
     
    131127                        , decltype( node->accept(*this) )
    132128                >::type
     129
    133130        {
    134131                __pedantic_pass_assert( __visit_children() );
    135                 __pedantic_pass_assert( node );
     132                __pedantic_pass_assert( expr );
    136133
    137134                static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR");
     
    141138        }
    142139
    143         template< typename core_t >
    144         const ast::Expr * ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
     140        template< typename pass_t >
     141        const ast::Expr * ast::Pass< pass_t >::call_accept( const ast::Expr * expr ) {
    145142                __pedantic_pass_assert( __visit_children() );
    146143                __pedantic_pass_assert( expr );
    147144
    148                 const ast::TypeSubstitution ** env_ptr = __pass::env( core, 0);
     145                const ast::TypeSubstitution ** env_ptr = __pass::env( pass, 0);
    149146                if ( env_ptr && expr->env ) {
    150147                        *env_ptr = expr->env;
     
    154151        }
    155152
    156         template< typename core_t >
    157         const ast::Stmt * ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
     153        template< typename pass_t >
     154        const ast::Stmt * ast::Pass< pass_t >::call_accept( const ast::Stmt * stmt ) {
    158155                __pedantic_pass_assert( __visit_children() );
    159156                __pedantic_pass_assert( stmt );
     
    163160
    164161                // get the stmts/decls that will need to be spliced in
    165                 auto stmts_before = __pass::stmtsToAddBefore( core, 0);
    166                 auto stmts_after  = __pass::stmtsToAddAfter ( core, 0);
    167                 auto decls_before = __pass::declsToAddBefore( core, 0);
    168                 auto decls_after  = __pass::declsToAddAfter ( core, 0);
     162                auto stmts_before = __pass::stmtsToAddBefore( pass, 0);
     163                auto stmts_after  = __pass::stmtsToAddAfter ( pass, 0);
     164                auto decls_before = __pass::declsToAddBefore( pass, 0);
     165                auto decls_after  = __pass::declsToAddAfter ( pass, 0);
    169166
    170167                // These may be modified by subnode but most be restored once we exit this statemnet.
    171                 ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::env( core, 0) );
     168                ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::env( pass, 0) );
    172169                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
    173170                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
     
    205202        }
    206203
    207         template< typename core_t >
     204        template< typename pass_t >
    208205        template< template <class...> class container_t >
    209         container_t< ptr<Stmt> > ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
     206        container_t< ptr<Stmt> > ast::Pass< pass_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
    210207                __pedantic_pass_assert( __visit_children() );
    211208                if( statements.empty() ) return {};
     
    218215
    219216                // get the stmts/decls that will need to be spliced in
    220                 auto stmts_before = __pass::stmtsToAddBefore( core, 0);
    221                 auto stmts_after  = __pass::stmtsToAddAfter ( core, 0);
    222                 auto decls_before = __pass::declsToAddBefore( core, 0);
    223                 auto decls_after  = __pass::declsToAddAfter ( core, 0);
     217                auto stmts_before = __pass::stmtsToAddBefore( pass, 0);
     218                auto stmts_after  = __pass::stmtsToAddAfter ( pass, 0);
     219                auto decls_before = __pass::declsToAddBefore( pass, 0);
     220                auto decls_after  = __pass::declsToAddAfter ( pass, 0);
    224221
    225222                // These may be modified by subnode but most be restored once we exit this statemnet.
     
    271268        }
    272269
    273         template< typename core_t >
     270        template< typename pass_t >
    274271        template< template <class...> class container_t, typename node_t >
    275         container_t< ast::ptr<node_t> > ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
     272        container_t< ast::ptr<node_t> > ast::Pass< pass_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
    276273                __pedantic_pass_assert( __visit_children() );
    277274                if( container.empty() ) return {};
     
    302299        }
    303300
    304         template< typename core_t >
     301        template< typename pass_t >
    305302        template<typename node_t, typename parent_t, typename child_t>
    306         void ast::Pass< core_t >::maybe_accept(
     303        void ast::Pass< pass_t >::maybe_accept(
    307304                const node_t * & parent,
    308305                child_t parent_t::*child
     
    326323        }
    327324
    328 
    329         template< typename core_t >
    330         template< typename node_t >
    331         void ast::Pass< core_t >::mutate_forall( const node_t *& node ) {
    332                 if ( auto subs = __pass::forall::subs( core, 0 ) ) {
    333                         // tracking TypeDecl substitution, full clone
    334                         if ( node->forall.empty() ) return;
    335 
    336                         node_t * mut = mutate( node );
    337                         mut->forall = subs->clone( node->forall, *this );
    338                         node = mut;
    339                 } else {
    340                         // not tracking TypeDecl substitution, just mutate
    341                         maybe_accept( node, &node_t::forall );
    342                 }
    343         }
    344325}
    345326
     
    352333//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    353334
    354 template< typename core_t >
    355 inline void ast::accept_all( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< core_t > & visitor ) {
     335template< typename pass_t >
     336inline void ast::accept_all( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< pass_t > & visitor ) {
    356337        // We are going to aggregate errors for all these statements
    357338        SemanticErrorException errors;
     
    361342
    362343        // get the stmts/decls that will need to be spliced in
    363         auto decls_before = __pass::declsToAddBefore( visitor.core, 0);
    364         auto decls_after  = __pass::declsToAddAfter ( visitor.core, 0);
     344        auto decls_before = __pass::declsToAddBefore( visitor.pass, 0);
     345        auto decls_after  = __pass::declsToAddAfter ( visitor.pass, 0);
    365346
    366347        // update pass statitistics
     
    411392//--------------------------------------------------------------------------
    412393// ObjectDecl
    413 template< typename core_t >
    414 const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::ObjectDecl * node ) {
     394template< typename pass_t >
     395const ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::ObjectDecl * node ) {
    415396        VISIT_START( node );
    416397
     
    425406        )
    426407
    427         __pass::symtab::addId( core, 0, node );
     408        __pass::symtab::addId( pass, 0, node );
    428409
    429410        VISIT_END( DeclWithType, node );
     
    432413//--------------------------------------------------------------------------
    433414// FunctionDecl
    434 template< typename core_t >
    435 const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::FunctionDecl * node ) {
    436         VISIT_START( node );
    437 
    438         __pass::symtab::addId( core, 0, node );
     415template< typename pass_t >
     416const ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::FunctionDecl * node ) {
     417        VISIT_START( node );
     418
     419        __pass::symtab::addId( pass, 0, node );
    439420
    440421        VISIT(maybe_accept( node, &FunctionDecl::withExprs );)
     
    444425                // shadow with exprs and not the other way around.
    445426                guard_symtab guard { *this };
    446                 __pass::symtab::addWith( core, 0, node->withExprs, node );
     427                __pass::symtab::addWith( pass, 0, node->withExprs, node );
    447428                {
    448429                        guard_symtab guard { *this };
    449430                        // implicit add __func__ identifier as specified in the C manual 6.4.2.2
    450                         static ast::ptr< ast::ObjectDecl > func{ new ast::ObjectDecl{
    451                                 CodeLocation{}, "__func__",
    452                                 new ast::ArrayType{
    453                                         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 ) ),
    454435                                        nullptr, VariableLen, DynamicDim
    455                                 }
    456                         } };
    457                         __pass::symtab::addId( core, 0, func );
     436                                )
     437                        );
     438                        __pass::symtab::addId( pass, 0, &func );
    458439                        VISIT(
    459440                                maybe_accept( node, &FunctionDecl::type );
     
    473454//--------------------------------------------------------------------------
    474455// StructDecl
    475 template< typename core_t >
    476 const ast::Decl * ast::Pass< core_t >::visit( const ast::StructDecl * node ) {
     456template< typename pass_t >
     457const ast::Decl * ast::Pass< pass_t >::visit( const ast::StructDecl * node ) {
    477458        VISIT_START( node );
    478459
    479460        // make up a forward declaration and add it before processing the members
    480461        // needs to be on the heap because addStruct saves the pointer
    481         __pass::symtab::addStructFwd( core, 0, node );
     462        __pass::symtab::addStructFwd( pass, 0, node );
    482463
    483464        VISIT({
     
    488469
    489470        // this addition replaces the forward declaration
    490         __pass::symtab::addStruct( core, 0, node );
     471        __pass::symtab::addStruct( pass, 0, node );
    491472
    492473        VISIT_END( Decl, node );
     
    495476//--------------------------------------------------------------------------
    496477// UnionDecl
    497 template< typename core_t >
    498 const ast::Decl * ast::Pass< core_t >::visit( const ast::UnionDecl * node ) {
     478template< typename pass_t >
     479const ast::Decl * ast::Pass< pass_t >::visit( const ast::UnionDecl * node ) {
    499480        VISIT_START( node );
    500481
    501482        // make up a forward declaration and add it before processing the members
    502         __pass::symtab::addUnionFwd( core, 0, node );
     483        __pass::symtab::addUnionFwd( pass, 0, node );
    503484
    504485        VISIT({
     
    508489        })
    509490
    510         __pass::symtab::addUnion( core, 0, node );
     491        __pass::symtab::addUnion( pass, 0, node );
    511492
    512493        VISIT_END( Decl, node );
     
    515496//--------------------------------------------------------------------------
    516497// EnumDecl
    517 template< typename core_t >
    518 const ast::Decl * ast::Pass< core_t >::visit( const ast::EnumDecl * node ) {
    519         VISIT_START( node );
    520 
    521         __pass::symtab::addEnum( core, 0, node );
     498template< typename pass_t >
     499const ast::Decl * ast::Pass< pass_t >::visit( const ast::EnumDecl * node ) {
     500        VISIT_START( node );
     501
     502        __pass::symtab::addEnum( pass, 0, node );
    522503
    523504        VISIT(
     
    532513//--------------------------------------------------------------------------
    533514// TraitDecl
    534 template< typename core_t >
    535 const ast::Decl * ast::Pass< core_t >::visit( const ast::TraitDecl * node ) {
     515template< typename pass_t >
     516const ast::Decl * ast::Pass< pass_t >::visit( const ast::TraitDecl * node ) {
    536517        VISIT_START( node );
    537518
     
    542523        })
    543524
    544         __pass::symtab::addTrait( core, 0, node );
     525        __pass::symtab::addTrait( pass, 0, node );
    545526
    546527        VISIT_END( Decl, node );
     
    549530//--------------------------------------------------------------------------
    550531// TypeDecl
    551 template< typename core_t >
    552 const ast::Decl * ast::Pass< core_t >::visit( const ast::TypeDecl * node ) {
     532template< typename pass_t >
     533const ast::Decl * ast::Pass< pass_t >::visit( const ast::TypeDecl * node ) {
    553534        VISIT_START( node );
    554535
     
    562543        // note that assertions come after the type is added to the symtab, since they are not part of the type proper
    563544        // and may depend on the type itself
    564         __pass::symtab::addType( core, 0, node );
     545        __pass::symtab::addType( pass, 0, node );
    565546
    566547        VISIT(
     
    578559//--------------------------------------------------------------------------
    579560// TypedefDecl
    580 template< typename core_t >
    581 const ast::Decl * ast::Pass< core_t >::visit( const ast::TypedefDecl * node ) {
     561template< typename pass_t >
     562const ast::Decl * ast::Pass< pass_t >::visit( const ast::TypedefDecl * node ) {
    582563        VISIT_START( node );
    583564
     
    588569        })
    589570
    590         __pass::symtab::addType( core, 0, node );
     571        __pass::symtab::addType( pass, 0, node );
    591572
    592573        VISIT( maybe_accept( node, &TypedefDecl::assertions ); )
     
    597578//--------------------------------------------------------------------------
    598579// AsmDecl
    599 template< typename core_t >
    600 const ast::AsmDecl * ast::Pass< core_t >::visit( const ast::AsmDecl * node ) {
     580template< typename pass_t >
     581const ast::AsmDecl * ast::Pass< pass_t >::visit( const ast::AsmDecl * node ) {
    601582        VISIT_START( node );
    602583
     
    610591//--------------------------------------------------------------------------
    611592// StaticAssertDecl
    612 template< typename core_t >
    613 const ast::StaticAssertDecl * ast::Pass< core_t >::visit( const ast::StaticAssertDecl * node ) {
     593template< typename pass_t >
     594const ast::StaticAssertDecl * ast::Pass< pass_t >::visit( const ast::StaticAssertDecl * node ) {
    614595        VISIT_START( node );
    615596
     
    624605//--------------------------------------------------------------------------
    625606// CompoundStmt
    626 template< typename core_t >
    627 const ast::CompoundStmt * ast::Pass< core_t >::visit( const ast::CompoundStmt * node ) {
     607template< typename pass_t >
     608const ast::CompoundStmt * ast::Pass< pass_t >::visit( const ast::CompoundStmt * node ) {
    628609        VISIT_START( node );
    629610        VISIT({
    630611                // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    631                 auto guard1 = makeFuncGuard( [this, inFunctionCpy = this->inFunction]() {
    632                         if ( ! inFunctionCpy ) __pass::symtab::enter(core, 0);
    633                 }, [this, inFunctionCpy = this->inFunction]() {
    634                         if ( ! inFunctionCpy ) __pass::symtab::leave(core, 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);
    635616                });
    636617                ValueGuard< bool > guard2( inFunction );
     
    644625//--------------------------------------------------------------------------
    645626// ExprStmt
    646 template< typename core_t >
    647 const ast::Stmt * ast::Pass< core_t >::visit( const ast::ExprStmt * node ) {
     627template< typename pass_t >
     628const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ExprStmt * node ) {
    648629        VISIT_START( node );
    649630
     
    657638//--------------------------------------------------------------------------
    658639// AsmStmt
    659 template< typename core_t >
    660 const ast::Stmt * ast::Pass< core_t >::visit( const ast::AsmStmt * node ) {
     640template< typename pass_t >
     641const ast::Stmt * ast::Pass< pass_t >::visit( const ast::AsmStmt * node ) {
    661642        VISIT_START( node )
    662643
     
    673654//--------------------------------------------------------------------------
    674655// DirectiveStmt
    675 template< typename core_t >
    676 const ast::Stmt * ast::Pass< core_t >::visit( const ast::DirectiveStmt * node ) {
     656template< typename pass_t >
     657const ast::Stmt * ast::Pass< pass_t >::visit( const ast::DirectiveStmt * node ) {
    677658        VISIT_START( node )
    678659
     
    682663//--------------------------------------------------------------------------
    683664// IfStmt
    684 template< typename core_t >
    685 const ast::Stmt * ast::Pass< core_t >::visit( const ast::IfStmt * node ) {
     665template< typename pass_t >
     666const ast::Stmt * ast::Pass< pass_t >::visit( const ast::IfStmt * node ) {
    686667        VISIT_START( node );
    687668
     
    700681//--------------------------------------------------------------------------
    701682// WhileStmt
    702 template< typename core_t >
    703 const ast::Stmt * ast::Pass< core_t >::visit( const ast::WhileStmt * node ) {
     683template< typename pass_t >
     684const ast::Stmt * ast::Pass< pass_t >::visit( const ast::WhileStmt * node ) {
    704685        VISIT_START( node );
    705686
     
    717698//--------------------------------------------------------------------------
    718699// ForStmt
    719 template< typename core_t >
    720 const ast::Stmt * ast::Pass< core_t >::visit( const ast::ForStmt * node ) {
     700template< typename pass_t >
     701const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ForStmt * node ) {
    721702        VISIT_START( node );
    722703
     
    735716//--------------------------------------------------------------------------
    736717// SwitchStmt
    737 template< typename core_t >
    738 const ast::Stmt * ast::Pass< core_t >::visit( const ast::SwitchStmt * node ) {
     718template< typename pass_t >
     719const ast::Stmt * ast::Pass< pass_t >::visit( const ast::SwitchStmt * node ) {
    739720        VISIT_START( node );
    740721
     
    749730//--------------------------------------------------------------------------
    750731// CaseStmt
    751 template< typename core_t >
    752 const ast::Stmt * ast::Pass< core_t >::visit( const ast::CaseStmt * node ) {
     732template< typename pass_t >
     733const ast::Stmt * ast::Pass< pass_t >::visit( const ast::CaseStmt * node ) {
    753734        VISIT_START( node );
    754735
     
    763744//--------------------------------------------------------------------------
    764745// BranchStmt
    765 template< typename core_t >
    766 const ast::Stmt * ast::Pass< core_t >::visit( const ast::BranchStmt * node ) {
     746template< typename pass_t >
     747const ast::Stmt * ast::Pass< pass_t >::visit( const ast::BranchStmt * node ) {
    767748        VISIT_START( node );
    768749        VISIT_END( Stmt, node );
     
    771752//--------------------------------------------------------------------------
    772753// ReturnStmt
    773 template< typename core_t >
    774 const ast::Stmt * ast::Pass< core_t >::visit( const ast::ReturnStmt * node ) {
     754template< typename pass_t >
     755const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ReturnStmt * node ) {
    775756        VISIT_START( node );
    776757
     
    784765//--------------------------------------------------------------------------
    785766// ThrowStmt
    786 template< typename core_t >
    787 const ast::Stmt * ast::Pass< core_t >::visit( const ast::ThrowStmt * node ) {
     767template< typename pass_t >
     768const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ThrowStmt * node ) {
    788769        VISIT_START( node );
    789770
     
    798779//--------------------------------------------------------------------------
    799780// TryStmt
    800 template< typename core_t >
    801 const ast::Stmt * ast::Pass< core_t >::visit( const ast::TryStmt * node ) {
     781template< typename pass_t >
     782const ast::Stmt * ast::Pass< pass_t >::visit( const ast::TryStmt * node ) {
    802783        VISIT_START( node );
    803784
     
    813794//--------------------------------------------------------------------------
    814795// CatchStmt
    815 template< typename core_t >
    816 const ast::Stmt * ast::Pass< core_t >::visit( const ast::CatchStmt * node ) {
     796template< typename pass_t >
     797const ast::Stmt * ast::Pass< pass_t >::visit( const ast::CatchStmt * node ) {
    817798        VISIT_START( node );
    818799
     
    830811//--------------------------------------------------------------------------
    831812// FinallyStmt
    832 template< typename core_t >
    833 const ast::Stmt * ast::Pass< core_t >::visit( const ast::FinallyStmt * node ) {
     813template< typename pass_t >
     814const ast::Stmt * ast::Pass< pass_t >::visit( const ast::FinallyStmt * node ) {
    834815        VISIT_START( node );
    835816
     
    843824//--------------------------------------------------------------------------
    844825// FinallyStmt
    845 template< typename core_t >
    846 const ast::Stmt * ast::Pass< core_t >::visit( const ast::SuspendStmt * node ) {
     826template< typename pass_t >
     827const ast::Stmt * ast::Pass< pass_t >::visit( const ast::SuspendStmt * node ) {
    847828        VISIT_START( node );
    848829
     
    856837//--------------------------------------------------------------------------
    857838// WaitForStmt
    858 template< typename core_t >
    859 const ast::Stmt * ast::Pass< core_t >::visit( const ast::WaitForStmt * node ) {
     839template< typename pass_t >
     840const ast::Stmt * ast::Pass< pass_t >::visit( const ast::WaitForStmt * node ) {
    860841        VISIT_START( node );
    861842                // for( auto & clause : node->clauses ) {
     
    925906//--------------------------------------------------------------------------
    926907// WithStmt
    927 template< typename core_t >
    928 const ast::Decl * ast::Pass< core_t >::visit( const ast::WithStmt * node ) {
     908template< typename pass_t >
     909const ast::Decl * ast::Pass< pass_t >::visit( const ast::WithStmt * node ) {
    929910        VISIT_START( node );
    930911
     
    934915                        // catch statements introduce a level of scope (for the caught exception)
    935916                        guard_symtab guard { *this };
    936                         __pass::symtab::addWith( core, 0, node->exprs, node );
     917                        __pass::symtab::addWith( pass, 0, node->exprs, node );
    937918                        maybe_accept( node, &WithStmt::stmt );
    938919                }
     
    943924//--------------------------------------------------------------------------
    944925// NullStmt
    945 template< typename core_t >
    946 const ast::NullStmt * ast::Pass< core_t >::visit( const ast::NullStmt * node ) {
     926template< typename pass_t >
     927const ast::NullStmt * ast::Pass< pass_t >::visit( const ast::NullStmt * node ) {
    947928        VISIT_START( node );
    948929        VISIT_END( NullStmt, node );
     
    951932//--------------------------------------------------------------------------
    952933// DeclStmt
    953 template< typename core_t >
    954 const ast::Stmt * ast::Pass< core_t >::visit( const ast::DeclStmt * node ) {
     934template< typename pass_t >
     935const ast::Stmt * ast::Pass< pass_t >::visit( const ast::DeclStmt * node ) {
    955936        VISIT_START( node );
    956937
     
    964945//--------------------------------------------------------------------------
    965946// ImplicitCtorDtorStmt
    966 template< typename core_t >
    967 const ast::Stmt * ast::Pass< core_t >::visit( const ast::ImplicitCtorDtorStmt * node ) {
     947template< typename pass_t >
     948const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ImplicitCtorDtorStmt * node ) {
    968949        VISIT_START( node );
    969950
    970951        // For now this isn't visited, it is unclear if this causes problem
    971952        // if all tests are known to pass, remove this code
    972         VISIT(
    973                 maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
    974         )
     953        // VISIT(
     954        //      maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
     955        // )
    975956
    976957        VISIT_END( Stmt, node );
     
    979960//--------------------------------------------------------------------------
    980961// ApplicationExpr
    981 template< typename core_t >
    982 const ast::Expr * ast::Pass< core_t >::visit( const ast::ApplicationExpr * node ) {
     962template< typename pass_t >
     963const ast::Expr * ast::Pass< pass_t >::visit( const ast::ApplicationExpr * node ) {
    983964        VISIT_START( node );
    984965
     
    997978//--------------------------------------------------------------------------
    998979// UntypedExpr
    999 template< typename core_t >
    1000 const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedExpr * node ) {
     980template< typename pass_t >
     981const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedExpr * node ) {
    1001982        VISIT_START( node );
    1002983
     
    1015996//--------------------------------------------------------------------------
    1016997// NameExpr
    1017 template< typename core_t >
    1018 const ast::Expr * ast::Pass< core_t >::visit( const ast::NameExpr * node ) {
     998template< typename pass_t >
     999const ast::Expr * ast::Pass< pass_t >::visit( const ast::NameExpr * node ) {
    10191000        VISIT_START( node );
    10201001
     
    10291010//--------------------------------------------------------------------------
    10301011// CastExpr
    1031 template< typename core_t >
    1032 const ast::Expr * ast::Pass< core_t >::visit( const ast::CastExpr * node ) {
     1012template< typename pass_t >
     1013const ast::Expr * ast::Pass< pass_t >::visit( const ast::CastExpr * node ) {
    10331014        VISIT_START( node );
    10341015
     
    10451026//--------------------------------------------------------------------------
    10461027// KeywordCastExpr
    1047 template< typename core_t >
    1048 const ast::Expr * ast::Pass< core_t >::visit( const ast::KeywordCastExpr * node ) {
     1028template< typename pass_t >
     1029const ast::Expr * ast::Pass< pass_t >::visit( const ast::KeywordCastExpr * node ) {
    10491030        VISIT_START( node );
    10501031
     
    10611042//--------------------------------------------------------------------------
    10621043// VirtualCastExpr
    1063 template< typename core_t >
    1064 const ast::Expr * ast::Pass< core_t >::visit( const ast::VirtualCastExpr * node ) {
     1044template< typename pass_t >
     1045const ast::Expr * ast::Pass< pass_t >::visit( const ast::VirtualCastExpr * node ) {
    10651046        VISIT_START( node );
    10661047
     
    10771058//--------------------------------------------------------------------------
    10781059// AddressExpr
    1079 template< typename core_t >
    1080 const ast::Expr * ast::Pass< core_t >::visit( const ast::AddressExpr * node ) {
     1060template< typename pass_t >
     1061const ast::Expr * ast::Pass< pass_t >::visit( const ast::AddressExpr * node ) {
    10811062        VISIT_START( node );
    10821063
     
    10931074//--------------------------------------------------------------------------
    10941075// LabelAddressExpr
    1095 template< typename core_t >
    1096 const ast::Expr * ast::Pass< core_t >::visit( const ast::LabelAddressExpr * node ) {
     1076template< typename pass_t >
     1077const ast::Expr * ast::Pass< pass_t >::visit( const ast::LabelAddressExpr * node ) {
    10971078        VISIT_START( node );
    10981079
     
    11071088//--------------------------------------------------------------------------
    11081089// UntypedMemberExpr
    1109 template< typename core_t >
    1110 const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedMemberExpr * node ) {
     1090template< typename pass_t >
     1091const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedMemberExpr * node ) {
    11111092        VISIT_START( node );
    11121093
     
    11241105//--------------------------------------------------------------------------
    11251106// MemberExpr
    1126 template< typename core_t >
    1127 const ast::Expr * ast::Pass< core_t >::visit( const ast::MemberExpr * node ) {
     1107template< typename pass_t >
     1108const ast::Expr * ast::Pass< pass_t >::visit( const ast::MemberExpr * node ) {
    11281109        VISIT_START( node );
    11291110
     
    11401121//--------------------------------------------------------------------------
    11411122// VariableExpr
    1142 template< typename core_t >
    1143 const ast::Expr * ast::Pass< core_t >::visit( const ast::VariableExpr * node ) {
     1123template< typename pass_t >
     1124const ast::Expr * ast::Pass< pass_t >::visit( const ast::VariableExpr * node ) {
    11441125        VISIT_START( node );
    11451126
     
    11541135//--------------------------------------------------------------------------
    11551136// ConstantExpr
    1156 template< typename core_t >
    1157 const ast::Expr * ast::Pass< core_t >::visit( const ast::ConstantExpr * node ) {
     1137template< typename pass_t >
     1138const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConstantExpr * node ) {
    11581139        VISIT_START( node );
    11591140
     
    11681149//--------------------------------------------------------------------------
    11691150// SizeofExpr
    1170 template< typename core_t >
    1171 const ast::Expr * ast::Pass< core_t >::visit( const ast::SizeofExpr * node ) {
     1151template< typename pass_t >
     1152const ast::Expr * ast::Pass< pass_t >::visit( const ast::SizeofExpr * node ) {
    11721153        VISIT_START( node );
    11731154
     
    11881169//--------------------------------------------------------------------------
    11891170// AlignofExpr
    1190 template< typename core_t >
    1191 const ast::Expr * ast::Pass< core_t >::visit( const ast::AlignofExpr * node ) {
     1171template< typename pass_t >
     1172const ast::Expr * ast::Pass< pass_t >::visit( const ast::AlignofExpr * node ) {
    11921173        VISIT_START( node );
    11931174
     
    12081189//--------------------------------------------------------------------------
    12091190// UntypedOffsetofExpr
    1210 template< typename core_t >
    1211 const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedOffsetofExpr * node ) {
     1191template< typename pass_t >
     1192const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedOffsetofExpr * node ) {
    12121193        VISIT_START( node );
    12131194
     
    12241205//--------------------------------------------------------------------------
    12251206// OffsetofExpr
    1226 template< typename core_t >
    1227 const ast::Expr * ast::Pass< core_t >::visit( const ast::OffsetofExpr * node ) {
     1207template< typename pass_t >
     1208const ast::Expr * ast::Pass< pass_t >::visit( const ast::OffsetofExpr * node ) {
    12281209        VISIT_START( node );
    12291210
     
    12401221//--------------------------------------------------------------------------
    12411222// OffsetPackExpr
    1242 template< typename core_t >
    1243 const ast::Expr * ast::Pass< core_t >::visit( const ast::OffsetPackExpr * node ) {
     1223template< typename pass_t >
     1224const ast::Expr * ast::Pass< pass_t >::visit( const ast::OffsetPackExpr * node ) {
    12441225        VISIT_START( node );
    12451226
     
    12561237//--------------------------------------------------------------------------
    12571238// LogicalExpr
    1258 template< typename core_t >
    1259 const ast::Expr * ast::Pass< core_t >::visit( const ast::LogicalExpr * node ) {
     1239template< typename pass_t >
     1240const ast::Expr * ast::Pass< pass_t >::visit( const ast::LogicalExpr * node ) {
    12601241        VISIT_START( node );
    12611242
     
    12731254//--------------------------------------------------------------------------
    12741255// ConditionalExpr
    1275 template< typename core_t >
    1276 const ast::Expr * ast::Pass< core_t >::visit( const ast::ConditionalExpr * node ) {
     1256template< typename pass_t >
     1257const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConditionalExpr * node ) {
    12771258        VISIT_START( node );
    12781259
     
    12911272//--------------------------------------------------------------------------
    12921273// CommaExpr
    1293 template< typename core_t >
    1294 const ast::Expr * ast::Pass< core_t >::visit( const ast::CommaExpr * node ) {
     1274template< typename pass_t >
     1275const ast::Expr * ast::Pass< pass_t >::visit( const ast::CommaExpr * node ) {
    12951276        VISIT_START( node );
    12961277
     
    13081289//--------------------------------------------------------------------------
    13091290// TypeExpr
    1310 template< typename core_t >
    1311 const ast::Expr * ast::Pass< core_t >::visit( const ast::TypeExpr * node ) {
     1291template< typename pass_t >
     1292const ast::Expr * ast::Pass< pass_t >::visit( const ast::TypeExpr * node ) {
    13121293        VISIT_START( node );
    13131294
     
    13241305//--------------------------------------------------------------------------
    13251306// AsmExpr
    1326 template< typename core_t >
    1327 const ast::Expr * ast::Pass< core_t >::visit( const ast::AsmExpr * node ) {
     1307template< typename pass_t >
     1308const ast::Expr * ast::Pass< pass_t >::visit( const ast::AsmExpr * node ) {
    13281309        VISIT_START( node );
    13291310
     
    13411322//--------------------------------------------------------------------------
    13421323// ImplicitCopyCtorExpr
    1343 template< typename core_t >
    1344 const ast::Expr * ast::Pass< core_t >::visit( const ast::ImplicitCopyCtorExpr * node ) {
     1324template< typename pass_t >
     1325const ast::Expr * ast::Pass< pass_t >::visit( const ast::ImplicitCopyCtorExpr * node ) {
    13451326        VISIT_START( node );
    13461327
     
    13571338//--------------------------------------------------------------------------
    13581339// ConstructorExpr
    1359 template< typename core_t >
    1360 const ast::Expr * ast::Pass< core_t >::visit( const ast::ConstructorExpr * node ) {
     1340template< typename pass_t >
     1341const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConstructorExpr * node ) {
    13611342        VISIT_START( node );
    13621343
     
    13731354//--------------------------------------------------------------------------
    13741355// CompoundLiteralExpr
    1375 template< typename core_t >
    1376 const ast::Expr * ast::Pass< core_t >::visit( const ast::CompoundLiteralExpr * node ) {
     1356template< typename pass_t >
     1357const ast::Expr * ast::Pass< pass_t >::visit( const ast::CompoundLiteralExpr * node ) {
    13771358        VISIT_START( node );
    13781359
     
    13891370//--------------------------------------------------------------------------
    13901371// RangeExpr
    1391 template< typename core_t >
    1392 const ast::Expr * ast::Pass< core_t >::visit( const ast::RangeExpr * node ) {
     1372template< typename pass_t >
     1373const ast::Expr * ast::Pass< pass_t >::visit( const ast::RangeExpr * node ) {
    13931374        VISIT_START( node );
    13941375
     
    14061387//--------------------------------------------------------------------------
    14071388// UntypedTupleExpr
    1408 template< typename core_t >
    1409 const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedTupleExpr * node ) {
     1389template< typename pass_t >
     1390const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedTupleExpr * node ) {
    14101391        VISIT_START( node );
    14111392
     
    14221403//--------------------------------------------------------------------------
    14231404// TupleExpr
    1424 template< typename core_t >
    1425 const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleExpr * node ) {
     1405template< typename pass_t >
     1406const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleExpr * node ) {
    14261407        VISIT_START( node );
    14271408
     
    14381419//--------------------------------------------------------------------------
    14391420// TupleIndexExpr
    1440 template< typename core_t >
    1441 const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleIndexExpr * node ) {
     1421template< typename pass_t >
     1422const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleIndexExpr * node ) {
    14421423        VISIT_START( node );
    14431424
     
    14541435//--------------------------------------------------------------------------
    14551436// TupleAssignExpr
    1456 template< typename core_t >
    1457 const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleAssignExpr * node ) {
     1437template< typename pass_t >
     1438const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleAssignExpr * node ) {
    14581439        VISIT_START( node );
    14591440
     
    14701451//--------------------------------------------------------------------------
    14711452// StmtExpr
    1472 template< typename core_t >
    1473 const ast::Expr * ast::Pass< core_t >::visit( const ast::StmtExpr * node ) {
     1453template< typename pass_t >
     1454const ast::Expr * ast::Pass< pass_t >::visit( const ast::StmtExpr * node ) {
    14741455        VISIT_START( node );
    14751456
    14761457        VISIT(// don't want statements from outer CompoundStmts to be added to this StmtExpr
    14771458                // get the stmts that will need to be spliced in
    1478                 auto stmts_before = __pass::stmtsToAddBefore( core, 0);
    1479                 auto stmts_after  = __pass::stmtsToAddAfter ( core, 0);
     1459                auto stmts_before = __pass::stmtsToAddBefore( pass, 0);
     1460                auto stmts_after  = __pass::stmtsToAddAfter ( pass, 0);
    14801461
    14811462                // These may be modified by subnode but most be restored once we exit this statemnet.
    1482                 ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::env( core, 0) );
     1463                ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::env( pass, 0) );
    14831464                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
    14841465                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
     
    14981479//--------------------------------------------------------------------------
    14991480// UniqueExpr
    1500 template< typename core_t >
    1501 const ast::Expr * ast::Pass< core_t >::visit( const ast::UniqueExpr * node ) {
     1481template< typename pass_t >
     1482const ast::Expr * ast::Pass< pass_t >::visit( const ast::UniqueExpr * node ) {
    15021483        VISIT_START( node );
    15031484
     
    15141495//--------------------------------------------------------------------------
    15151496// UntypedInitExpr
    1516 template< typename core_t >
    1517 const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedInitExpr * node ) {
     1497template< typename pass_t >
     1498const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedInitExpr * node ) {
    15181499        VISIT_START( node );
    15191500
     
    15311512//--------------------------------------------------------------------------
    15321513// InitExpr
    1533 template< typename core_t >
    1534 const ast::Expr * ast::Pass< core_t >::visit( const ast::InitExpr * node ) {
     1514template< typename pass_t >
     1515const ast::Expr * ast::Pass< pass_t >::visit( const ast::InitExpr * node ) {
    15351516        VISIT_START( node );
    15361517
     
    15481529//--------------------------------------------------------------------------
    15491530// DeletedExpr
    1550 template< typename core_t >
    1551 const ast::Expr * ast::Pass< core_t >::visit( const ast::DeletedExpr * node ) {
     1531template< typename pass_t >
     1532const ast::Expr * ast::Pass< pass_t >::visit( const ast::DeletedExpr * node ) {
    15521533        VISIT_START( node );
    15531534
     
    15651546//--------------------------------------------------------------------------
    15661547// DefaultArgExpr
    1567 template< typename core_t >
    1568 const ast::Expr * ast::Pass< core_t >::visit( const ast::DefaultArgExpr * node ) {
     1548template< typename pass_t >
     1549const ast::Expr * ast::Pass< pass_t >::visit( const ast::DefaultArgExpr * node ) {
    15691550        VISIT_START( node );
    15701551
     
    15811562//--------------------------------------------------------------------------
    15821563// GenericExpr
    1583 template< typename core_t >
    1584 const ast::Expr * ast::Pass< core_t >::visit( const ast::GenericExpr * node ) {
     1564template< typename pass_t >
     1565const ast::Expr * ast::Pass< pass_t >::visit( const ast::GenericExpr * node ) {
    15851566        VISIT_START( node );
    15861567
     
    16211602//--------------------------------------------------------------------------
    16221603// VoidType
    1623 template< typename core_t >
    1624 const ast::Type * ast::Pass< core_t >::visit( const ast::VoidType * node ) {
     1604template< typename pass_t >
     1605const ast::Type * ast::Pass< pass_t >::visit( const ast::VoidType * node ) {
    16251606        VISIT_START( node );
    16261607
     
    16301611//--------------------------------------------------------------------------
    16311612// BasicType
    1632 template< typename core_t >
    1633 const ast::Type * ast::Pass< core_t >::visit( const ast::BasicType * node ) {
     1613template< typename pass_t >
     1614const ast::Type * ast::Pass< pass_t >::visit( const ast::BasicType * node ) {
    16341615        VISIT_START( node );
    16351616
     
    16391620//--------------------------------------------------------------------------
    16401621// PointerType
    1641 template< typename core_t >
    1642 const ast::Type * ast::Pass< core_t >::visit( const ast::PointerType * node ) {
     1622template< typename pass_t >
     1623const ast::Type * ast::Pass< pass_t >::visit( const ast::PointerType * node ) {
    16431624        VISIT_START( node );
    16441625
     
    16531634//--------------------------------------------------------------------------
    16541635// ArrayType
    1655 template< typename core_t >
    1656 const ast::Type * ast::Pass< core_t >::visit( const ast::ArrayType * node ) {
     1636template< typename pass_t >
     1637const ast::Type * ast::Pass< pass_t >::visit( const ast::ArrayType * node ) {
    16571638        VISIT_START( node );
    16581639
     
    16671648//--------------------------------------------------------------------------
    16681649// ReferenceType
    1669 template< typename core_t >
    1670 const ast::Type * ast::Pass< core_t >::visit( const ast::ReferenceType * node ) {
     1650template< typename pass_t >
     1651const ast::Type * ast::Pass< pass_t >::visit( const ast::ReferenceType * node ) {
    16711652        VISIT_START( node );
    16721653
     
    16801661//--------------------------------------------------------------------------
    16811662// QualifiedType
    1682 template< typename core_t >
    1683 const ast::Type * ast::Pass< core_t >::visit( const ast::QualifiedType * node ) {
     1663template< typename pass_t >
     1664const ast::Type * ast::Pass< pass_t >::visit( const ast::QualifiedType * node ) {
    16841665        VISIT_START( node );
    16851666
     
    16941675//--------------------------------------------------------------------------
    16951676// FunctionType
    1696 template< typename core_t >
    1697 const ast::Type * ast::Pass< core_t >::visit( const ast::FunctionType * node ) {
    1698         VISIT_START( node );
    1699 
    1700         VISIT({
    1701                 guard_forall_subs forall_guard { *this, node };
    1702                 mutate_forall( node );
     1677template< typename pass_t >
     1678const ast::Type * ast::Pass< pass_t >::visit( const ast::FunctionType * node ) {
     1679        VISIT_START( node );
     1680
     1681        VISIT(
     1682                maybe_accept( node, &FunctionType::forall  );
    17031683                maybe_accept( node, &FunctionType::returns );
    17041684                maybe_accept( node, &FunctionType::params  );
    1705         })
     1685        )
    17061686
    17071687        VISIT_END( Type, node );
     
    17101690//--------------------------------------------------------------------------
    17111691// StructInstType
    1712 template< typename core_t >
    1713 const ast::Type * ast::Pass< core_t >::visit( const ast::StructInstType * node ) {
    1714         VISIT_START( node );
    1715 
    1716         __pass::symtab::addStruct( core, 0, node->name );
     1692template< typename pass_t >
     1693const ast::Type * ast::Pass< pass_t >::visit( const ast::StructInstType * node ) {
     1694        VISIT_START( node );
     1695
     1696        __pass::symtab::addStruct( pass, 0, node->name );
    17171697
    17181698        VISIT({
    17191699                guard_symtab guard { *this };
    1720                 guard_forall_subs forall_guard { *this, node };
    1721                 mutate_forall( node );
     1700                maybe_accept( node, &StructInstType::forall );
    17221701                maybe_accept( node, &StructInstType::params );
    17231702        })
     
    17281707//--------------------------------------------------------------------------
    17291708// UnionInstType
    1730 template< typename core_t >
    1731 const ast::Type * ast::Pass< core_t >::visit( const ast::UnionInstType * node ) {
    1732         VISIT_START( node );
    1733 
    1734         __pass::symtab::addUnion( core, 0, node->name );
    1735 
    1736         VISIT({
     1709template< typename pass_t >
     1710const ast::Type * ast::Pass< pass_t >::visit( const ast::UnionInstType * node ) {
     1711        VISIT_START( node );
     1712
     1713        __pass::symtab::addStruct( pass, 0, node->name );
     1714
     1715        {
    17371716                guard_symtab guard { *this };
    1738                 guard_forall_subs forall_guard { *this, node };
    1739                 mutate_forall( node );
     1717                maybe_accept( node, &UnionInstType::forall );
    17401718                maybe_accept( node, &UnionInstType::params );
    1741         })
     1719        }
    17421720
    17431721        VISIT_END( Type, node );
     
    17461724//--------------------------------------------------------------------------
    17471725// EnumInstType
    1748 template< typename core_t >
    1749 const ast::Type * ast::Pass< core_t >::visit( const ast::EnumInstType * node ) {
    1750         VISIT_START( node );
    1751 
    1752         VISIT({
    1753                 guard_forall_subs forall_guard { *this, node };
    1754                 mutate_forall( node );
     1726template< typename pass_t >
     1727const ast::Type * ast::Pass< pass_t >::visit( const ast::EnumInstType * node ) {
     1728        VISIT_START( node );
     1729
     1730        VISIT(
     1731                maybe_accept( node, &EnumInstType::forall );
    17551732                maybe_accept( node, &EnumInstType::params );
    1756         })
     1733        )
    17571734
    17581735        VISIT_END( Type, node );
     
    17611738//--------------------------------------------------------------------------
    17621739// TraitInstType
    1763 template< typename core_t >
    1764 const ast::Type * ast::Pass< core_t >::visit( const ast::TraitInstType * node ) {
    1765         VISIT_START( node );
    1766 
    1767         VISIT({
    1768                 guard_forall_subs forall_guard { *this, node };
    1769                 mutate_forall( node );
     1740template< typename pass_t >
     1741const ast::Type * ast::Pass< pass_t >::visit( const ast::TraitInstType * node ) {
     1742        VISIT_START( node );
     1743
     1744        VISIT(
     1745                maybe_accept( node, &TraitInstType::forall );
    17701746                maybe_accept( node, &TraitInstType::params );
    1771         })
     1747        )
    17721748
    17731749        VISIT_END( Type, node );
     
    17761752//--------------------------------------------------------------------------
    17771753// TypeInstType
    1778 template< typename core_t >
    1779 const ast::Type * ast::Pass< core_t >::visit( const ast::TypeInstType * node ) {
    1780         VISIT_START( node );
    1781 
    1782         VISIT(
    1783                 {
    1784                         guard_forall_subs forall_guard { *this, node };
    1785                         mutate_forall( node );
    1786                         maybe_accept( node, &TypeInstType::params );
    1787                 }
    1788                 // ensure that base re-bound if doing substitution
    1789                 __pass::forall::replace( core, 0, node );
     1754template< typename pass_t >
     1755const ast::Type * ast::Pass< pass_t >::visit( const ast::TypeInstType * node ) {
     1756        VISIT_START( node );
     1757
     1758        VISIT(
     1759                maybe_accept( node, &TypeInstType::forall );
     1760                maybe_accept( node, &TypeInstType::params );
    17901761        )
    17911762
     
    17951766//--------------------------------------------------------------------------
    17961767// TupleType
    1797 template< typename core_t >
    1798 const ast::Type * ast::Pass< core_t >::visit( const ast::TupleType * node ) {
     1768template< typename pass_t >
     1769const ast::Type * ast::Pass< pass_t >::visit( const ast::TupleType * node ) {
    17991770        VISIT_START( node );
    18001771
     
    18091780//--------------------------------------------------------------------------
    18101781// TypeofType
    1811 template< typename core_t >
    1812 const ast::Type * ast::Pass< core_t >::visit( const ast::TypeofType * node ) {
     1782template< typename pass_t >
     1783const ast::Type * ast::Pass< pass_t >::visit( const ast::TypeofType * node ) {
    18131784        VISIT_START( node );
    18141785
     
    18221793//--------------------------------------------------------------------------
    18231794// VarArgsType
    1824 template< typename core_t >
    1825 const ast::Type * ast::Pass< core_t >::visit( const ast::VarArgsType * node ) {
     1795template< typename pass_t >
     1796const ast::Type * ast::Pass< pass_t >::visit( const ast::VarArgsType * node ) {
    18261797        VISIT_START( node );
    18271798
     
    18311802//--------------------------------------------------------------------------
    18321803// ZeroType
    1833 template< typename core_t >
    1834 const ast::Type * ast::Pass< core_t >::visit( const ast::ZeroType * node ) {
     1804template< typename pass_t >
     1805const ast::Type * ast::Pass< pass_t >::visit( const ast::ZeroType * node ) {
    18351806        VISIT_START( node );
    18361807
     
    18401811//--------------------------------------------------------------------------
    18411812// OneType
    1842 template< typename core_t >
    1843 const ast::Type * ast::Pass< core_t >::visit( const ast::OneType * node ) {
     1813template< typename pass_t >
     1814const ast::Type * ast::Pass< pass_t >::visit( const ast::OneType * node ) {
    18441815        VISIT_START( node );
    18451816
     
    18491820//--------------------------------------------------------------------------
    18501821// GlobalScopeType
    1851 template< typename core_t >
    1852 const ast::Type * ast::Pass< core_t >::visit( const ast::GlobalScopeType * node ) {
     1822template< typename pass_t >
     1823const ast::Type * ast::Pass< pass_t >::visit( const ast::GlobalScopeType * node ) {
    18531824        VISIT_START( node );
    18541825
     
    18591830//--------------------------------------------------------------------------
    18601831// Designation
    1861 template< typename core_t >
    1862 const ast::Designation * ast::Pass< core_t >::visit( const ast::Designation * node ) {
     1832template< typename pass_t >
     1833const ast::Designation * ast::Pass< pass_t >::visit( const ast::Designation * node ) {
    18631834        VISIT_START( node );
    18641835
     
    18701841//--------------------------------------------------------------------------
    18711842// SingleInit
    1872 template< typename core_t >
    1873 const ast::Init * ast::Pass< core_t >::visit( const ast::SingleInit * node ) {
     1843template< typename pass_t >
     1844const ast::Init * ast::Pass< pass_t >::visit( const ast::SingleInit * node ) {
    18741845        VISIT_START( node );
    18751846
     
    18831854//--------------------------------------------------------------------------
    18841855// ListInit
    1885 template< typename core_t >
    1886 const ast::Init * ast::Pass< core_t >::visit( const ast::ListInit * node ) {
     1856template< typename pass_t >
     1857const ast::Init * ast::Pass< pass_t >::visit( const ast::ListInit * node ) {
    18871858        VISIT_START( node );
    18881859
     
    18971868//--------------------------------------------------------------------------
    18981869// ConstructorInit
    1899 template< typename core_t >
    1900 const ast::Init * ast::Pass< core_t >::visit( const ast::ConstructorInit * node ) {
     1870template< typename pass_t >
     1871const ast::Init * ast::Pass< pass_t >::visit( const ast::ConstructorInit * node ) {
    19011872        VISIT_START( node );
    19021873
     
    19121883//--------------------------------------------------------------------------
    19131884// Attribute
    1914 template< typename core_t >
    1915 const ast::Attribute * ast::Pass< core_t >::visit( const ast::Attribute * node  )  {
     1885template< typename pass_t >
     1886const ast::Attribute * ast::Pass< pass_t >::visit( const ast::Attribute * node  )  {
    19161887        VISIT_START( node );
    19171888
     
    19251896//--------------------------------------------------------------------------
    19261897// TypeSubstitution
    1927 template< typename core_t >
    1928 const ast::TypeSubstitution * ast::Pass< core_t >::visit( const ast::TypeSubstitution * node ) {
     1898template< typename pass_t >
     1899const ast::TypeSubstitution * ast::Pass< pass_t >::visit( const ast::TypeSubstitution * node ) {
    19291900        VISIT_START( node );
    19301901
     
    19361907                                guard_symtab guard { *this };
    19371908                                auto new_node = p.second->accept( *this );
    1938                                 if (new_node != p.second) mutated = true;
     1909                                if (new_node != p.second) mutated = false;
    19391910                                new_map.insert({ p.first, new_node });
    19401911                        }
     
    19521923                                guard_symtab guard { *this };
    19531924                                auto new_node = p.second->accept( *this );
    1954                                 if (new_node != p.second) mutated = true;
     1925                                if (new_node != p.second) mutated = false;
    19551926                                new_map.insert({ p.first, new_node });
    19561927                        }
  • src/AST/Pass.proto.hpp

    rfb0ae06 rdab09ad  
    1717// IWYU pragma: private, include "Pass.hpp"
    1818
    19 #include "Common/Stats/Heap.h"
    20 
    2119namespace ast {
    22 template<typename core_t>
     20template<typename pass_type>
    2321class Pass;
    2422
     
    8482                };
    8583
    86                 std::stack< cleanup_t, std::vector<cleanup_t> > cleanups;
     84                std::stack< cleanup_t > cleanups;
    8785        };
    8886
     
    113111        /// "Short hand" to check if this is a valid previsit function
    114112        /// Mostly used to make the static_assert look (and print) prettier
    115         template<typename core_t, typename node_t>
     113        template<typename pass_t, typename node_t>
    116114        struct is_valid_previsit {
    117                 using ret_t = decltype( ((core_t*)nullptr)->previsit( (const node_t *)nullptr ) );
     115                using ret_t = decltype( ((pass_t*)nullptr)->previsit( (const node_t *)nullptr ) );
    118116
    119117                static constexpr bool value = std::is_void< ret_t >::value ||
     
    129127        template<>
    130128        struct __assign<true> {
    131                 template<typename core_t, typename node_t>
    132                 static inline void result( core_t & core, const node_t * & node ) {
    133                         core.previsit( node );
     129                template<typename pass_t, typename node_t>
     130                static inline void result( pass_t & pass, const node_t * & node ) {
     131                        pass.previsit( node );
    134132                }
    135133        };
     
    137135        template<>
    138136        struct __assign<false> {
    139                 template<typename core_t, typename node_t>
    140                 static inline void result( core_t & core, const node_t * & node ) {
    141                         node = core.previsit( node );
     137                template<typename pass_t, typename node_t>
     138                static inline void result( pass_t & pass, const node_t * & node ) {
     139                        node = pass.previsit( node );
    142140                        assertf(node, "Previsit must not return NULL");
    143141                }
     
    152150        template<>
    153151        struct __return<true> {
    154                 template<typename core_t, typename node_t>
    155                 static inline const node_t * result( core_t & core, const node_t * & node ) {
    156                         core.postvisit( node );
     152                template<typename pass_t, typename node_t>
     153                static inline const node_t * result( pass_t & pass, const node_t * & node ) {
     154                        pass.postvisit( node );
    157155                        return node;
    158156                }
     
    161159        template<>
    162160        struct __return<false> {
    163                 template<typename core_t, typename node_t>
    164                 static inline auto result( core_t & core, const node_t * & node ) {
    165                         return core.postvisit( node );
     161                template<typename pass_t, typename node_t>
     162                static inline auto result( pass_t & pass, const node_t * & node ) {
     163                        return pass.postvisit( node );
    166164                }
    167165        };
     
    182180        //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    183181        // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call
    184         template<typename core_t, typename node_t>
    185         static inline auto previsit( core_t & core, const node_t * & node, int ) -> decltype( core.previsit( node ), void() ) {
     182        template<typename pass_t, typename node_t>
     183        static inline auto previsit( pass_t & pass, const node_t * & node, int ) -> decltype( pass.previsit( node ), void() ) {
    186184                static_assert(
    187                         is_valid_previsit<core_t, node_t>::value,
     185                        is_valid_previsit<pass_t, node_t>::value,
    188186                        "Previsit may not change the type of the node. It must return its paremeter or void."
    189187                );
     
    191189                __assign<
    192190                        std::is_void<
    193                                 decltype( core.previsit( node ) )
     191                                decltype( pass.previsit( node ) )
    194192                        >::value
    195                 >::result( core, node );
     193                >::result( pass, node );
    196194        }
    197195
    198         template<typename core_t, typename node_t>
    199         static inline auto previsit( core_t &, const node_t *, long ) {}
     196        template<typename pass_t, typename node_t>
     197        static inline auto previsit( pass_t &, const node_t *, long ) {}
    200198
    201199        // PostVisit : never mutates the passed pointer but may return a different node
    202         template<typename core_t, typename node_t>
    203         static inline auto postvisit( core_t & core, const node_t * node, int ) ->
    204                 decltype( core.postvisit( node ), node->accept( *(Visitor*)nullptr ) )
     200        template<typename pass_t, typename node_t>
     201        static inline auto postvisit( pass_t & pass, const node_t * node, int ) ->
     202                decltype( pass.postvisit( node ), node->accept( *(Visitor*)nullptr ) )
    205203        {
    206204                return __return<
    207205                        std::is_void<
    208                                 decltype( core.postvisit( node ) )
     206                                decltype( pass.postvisit( node ) )
    209207                        >::value
    210                 >::result( core, node );
     208                >::result( pass, node );
    211209        }
    212210
    213         template<typename core_t, typename node_t>
    214         static inline const node_t * postvisit( core_t &, const node_t * node, long ) { return node; }
     211        template<typename pass_t, typename node_t>
     212        static inline const node_t * postvisit( pass_t &, const node_t * node, long ) { return node; }
    215213
    216214        //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     
    227225        // The type is not strictly enforced but does match the accessory
    228226        #define FIELD_PTR( name, default_type ) \
    229         template< typename core_t > \
    230         static inline auto name( core_t & core, int ) -> decltype( &core.name ) { return &core.name; } \
     227        template< typename pass_t > \
     228        static inline auto name( pass_t & pass, int ) -> decltype( &pass.name ) { return &pass.name; } \
    231229        \
    232         template< typename core_t > \
    233         static inline default_type * name( core_t &, long ) { return nullptr; }
     230        template< typename pass_t > \
     231        static inline default_type * name( pass_t &, long ) { return nullptr; }
    234232
    235233        // List of fields and their expected types
     
    241239        FIELD_PTR( visit_children, __pass::bool_ref )
    242240        FIELD_PTR( at_cleanup, __pass::at_cleanup_t )
    243         FIELD_PTR( visitor, ast::Pass<core_t> * const )
     241        FIELD_PTR( visitor, ast::Pass<pass_t> * const )
    244242
    245243        // Remove the macro to make sure we don't clash
    246244        #undef FIELD_PTR
    247 
    248         template< typename core_t >
    249         static inline auto beginTrace(core_t &, int) -> decltype( core_t::traceId, void() ) {
    250                 // Stats::Heap::stacktrace_push(core_t::traceId);
    251         }
    252 
    253         template< typename core_t >
    254         static inline auto endTrace(core_t &, int) -> decltype( core_t::traceId, void() ) {
    255                 // Stats::Heap::stacktrace_pop();
    256         }
    257 
    258         template< typename core_t >
    259         static void beginTrace(core_t &, long) {}
    260 
    261         template< typename core_t >
    262         static void endTrace(core_t &, long) {}
    263245
    264246        // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement.
     
    266248        // detect it using the same strategy
    267249        namespace scope {
    268                 template<typename core_t>
    269                 static inline auto enter( core_t & core, int ) -> decltype( core.beginScope(), void() ) {
    270                         core.beginScope();
    271                 }
    272 
    273                 template<typename core_t>
    274                 static inline void enter( core_t &, long ) {}
    275 
    276                 template<typename core_t>
    277                 static inline auto leave( core_t & core, int ) -> decltype( core.endScope(), void() ) {
    278                         core.endScope();
    279                 }
    280 
    281                 template<typename core_t>
    282                 static inline void leave( core_t &, long ) {}
    283         } // namespace scope
    284 
    285         // Certain passes desire an up to date symbol table automatically
     250                template<typename pass_t>
     251                static inline auto enter( pass_t & pass, int ) -> decltype( pass.beginScope(), void() ) {
     252                        pass.beginScope();
     253                }
     254
     255                template<typename pass_t>
     256                static inline void enter( pass_t &, long ) {}
     257
     258                template<typename pass_t>
     259                static inline auto leave( pass_t & pass, int ) -> decltype( pass.endScope(), void() ) {
     260                        pass.endScope();
     261                }
     262
     263                template<typename pass_t>
     264                static inline void leave( pass_t &, long ) {}
     265        };
     266
     267        // Finally certain pass desire an up to date symbol table automatically
    286268        // detect the presence of a member name `symtab` and call all the members appropriately
    287269        namespace symtab {
    288270                // Some simple scoping rules
    289                 template<typename core_t>
    290                 static inline auto enter( core_t & core, int ) -> decltype( core.symtab, void() ) {
    291                         core.symtab.enterScope();
    292                 }
    293 
    294                 template<typename core_t>
    295                 static inline auto enter( core_t &, long ) {}
    296 
    297                 template<typename core_t>
    298                 static inline auto leave( core_t & core, int ) -> decltype( core.symtab, void() ) {
    299                         core.symtab.leaveScope();
    300                 }
    301 
    302                 template<typename core_t>
    303                 static inline auto leave( core_t &, long ) {}
     271                template<typename pass_t>
     272                static inline auto enter( pass_t & pass, int ) -> decltype( pass.symtab.enterScope(), void() ) {
     273                        pass.symtab.enterScope();
     274                }
     275
     276                template<typename pass_t>
     277                static inline auto enter( pass_t &, long ) {}
     278
     279                template<typename pass_t>
     280                static inline auto leave( pass_t & pass, int ) -> decltype( pass.symtab.leaveScope(), void() ) {
     281                        pass.symtab.leaveScope();
     282                }
     283
     284                template<typename pass_t>
     285                static inline auto leave( pass_t &, long ) {}
    304286
    305287                // The symbol table has 2 kind of functions mostly, 1 argument and 2 arguments
    306288                // Create macro to condense these common patterns
    307289                #define SYMTAB_FUNC1( func, type ) \
    308                 template<typename core_t> \
    309                 static inline auto func( core_t & core, int, type arg ) -> decltype( core.symtab.func( arg ), void() ) {\
    310                         core.symtab.func( arg ); \
     290                template<typename pass_t> \
     291                static inline auto func( pass_t & pass, int, type arg ) -> decltype( pass.symtab.func( arg ), void() ) {\
     292                        pass.symtab.func( arg ); \
    311293                } \
    312294                \
    313                 template<typename core_t> \
    314                 static inline void func( core_t &, long, type ) {}
     295                template<typename pass_t> \
     296                static inline void func( pass_t &, long, type ) {}
    315297
    316298                #define SYMTAB_FUNC2( func, type1, type2 ) \
    317                 template<typename core_t> \
    318                 static inline auto func( core_t & core, int, type1 arg1, type2 arg2 ) -> decltype( core.symtab.func( arg1, arg2 ), void () ) {\
    319                         core.symtab.func( arg1, arg2 ); \
     299                template<typename pass_t> \
     300                static inline auto func( pass_t & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.symtab.func( arg1, arg2 ), void () ) {\
     301                        pass.symtab.func( arg1, arg2 ); \
    320302                } \
    321303                        \
    322                 template<typename core_t> \
    323                 static inline void func( core_t &, long, type1, type2 ) {}
     304                template<typename pass_t> \
     305                static inline void func( pass_t &, long, type1, type2 ) {}
    324306
    325307                SYMTAB_FUNC1( addId     , const DeclWithType *  );
     
    329311                SYMTAB_FUNC1( addUnion  , const UnionDecl *     );
    330312                SYMTAB_FUNC1( addTrait  , const TraitDecl *     );
    331                 SYMTAB_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Decl * );
     313                SYMTAB_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Node * );
    332314
    333315                // A few extra functions have more complicated behaviour, they are hand written
    334                 template<typename core_t>
    335                 static inline auto addStructFwd( core_t & core, int, const ast::StructDecl * decl ) -> decltype( core.symtab.addStruct( decl ), void() ) {
     316                template<typename pass_t>
     317                static inline auto addStructFwd( pass_t & pass, int, const ast::StructDecl * decl ) -> decltype( pass.symtab.addStruct( decl ), void() ) {
    336318                        ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name );
    337319                        fwd->params = decl->params;
    338                         core.symtab.addStruct( fwd );
    339                 }
    340 
    341                 template<typename core_t>
    342                 static inline void addStructFwd( core_t &, long, const ast::StructDecl * ) {}
    343 
    344                 template<typename core_t>
    345                 static inline auto addUnionFwd( core_t & core, int, const ast::UnionDecl * decl ) -> decltype( core.symtab.addUnion( decl ), void() ) {
     320                        pass.symtab.addStruct( fwd );
     321                }
     322
     323                template<typename pass_t>
     324                static inline void addStructFwd( pass_t &, long, const ast::StructDecl * ) {}
     325
     326                template<typename pass_t>
     327                static inline auto addUnionFwd( pass_t & pass, int, const ast::UnionDecl * decl ) -> decltype( pass.symtab.addUnion( decl ), void() ) {
    346328                        UnionDecl * fwd = new UnionDecl( decl->location, decl->name );
    347329                        fwd->params = decl->params;
    348                         core.symtab.addUnion( fwd );
    349                 }
    350 
    351                 template<typename core_t>
    352                 static inline void addUnionFwd( core_t &, long, const ast::UnionDecl * ) {}
    353 
    354                 template<typename core_t>
    355                 static inline auto addStruct( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addStruct( str ), void() ) {
    356                         if ( ! core.symtab.lookupStruct( str ) ) {
    357                                 core.symtab.addStruct( str );
    358                         }
    359                 }
    360 
    361                 template<typename core_t>
    362                 static inline void addStruct( core_t &, long, const std::string & ) {}
    363 
    364                 template<typename core_t>
    365                 static inline auto addUnion( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addUnion( str ), void() ) {
    366                         if ( ! core.symtab.lookupUnion( str ) ) {
    367                                 core.symtab.addUnion( str );
    368                         }
    369                 }
    370 
    371                 template<typename core_t>
    372                 static inline void addUnion( core_t &, long, const std::string & ) {}
     330                        pass.symtab.addUnion( fwd );
     331                }
     332
     333                template<typename pass_t>
     334                static inline void addUnionFwd( pass_t &, long, const ast::UnionDecl * ) {}
     335
     336                template<typename pass_t>
     337                static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass.symtab.addStruct( str ), void() ) {
     338                        if ( ! pass.symtab.lookupStruct( str ) ) {
     339                                pass.symtab.addStruct( str );
     340                        }
     341                }
     342
     343                template<typename pass_t>
     344                static inline void addStruct( pass_t &, long, const std::string & ) {}
     345
     346                template<typename pass_t>
     347                static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass.symtab.addUnion( str ), void() ) {
     348                        if ( ! pass.symtab.lookupUnion( str ) ) {
     349                                pass.symtab.addUnion( str );
     350                        }
     351                }
     352
     353                template<typename pass_t>
     354                static inline void addUnion( pass_t &, long, const std::string & ) {}
    373355
    374356                #undef SYMTAB_FUNC1
    375357                #undef SYMTAB_FUNC2
    376         } // namespace symtab
    377 
    378         // Some passes need to mutate TypeDecl and properly update their pointing TypeInstType.
    379         // Detect the presence of a member name `subs` and call all members appropriately
    380         namespace forall {
    381                 // Some simple scoping rules
    382                 template<typename core_t>
    383                 static inline auto enter( core_t & core, int, const ast::ParameterizedType * type )
    384                 -> decltype( core.subs, void() ) {
    385                         if ( ! type->forall.empty() ) core.subs.beginScope();
    386                 }
    387 
    388                 template<typename core_t>
    389                 static inline auto enter( core_t &, long, const ast::ParameterizedType * ) {}
    390 
    391                 template<typename core_t>
    392                 static inline auto leave( core_t & core, int, const ast::ParameterizedType * type )
    393                 -> decltype( core.subs, void() ) {
    394                         if ( ! type->forall.empty() ) { core.subs.endScope(); }
    395                 }
    396 
    397                 template<typename core_t>
    398                 static inline auto leave( core_t &, long, const ast::ParameterizedType * ) {}
    399 
    400                 // Get the substitution table, if present
    401                 template<typename core_t>
    402                 static inline auto subs( core_t & core, int ) -> decltype( &core.subs ) {
    403                         return &core.subs;
    404                 }
    405 
    406                 template<typename core_t>
    407                 static inline ast::ForallSubstitutionTable * subs( core_t &, long ) { return nullptr; }
    408 
    409                 // Replaces a TypeInstType's base TypeDecl according to the table
    410                 template<typename core_t>
    411                 static inline auto replace( core_t & core, int, const ast::TypeInstType *& inst )
    412                 -> decltype( core.subs, void() ) {
    413                         inst = ast::mutate_field(
    414                                 inst, &ast::TypeInstType::base, core.subs.replace( inst->base ) );
    415                 }
    416 
    417                 template<typename core_t>
    418                 static inline auto replace( core_t &, long, const ast::TypeInstType *& ) {}
    419 
    420         } // namespace forall
    421 } // namespace __pass
    422 } // namespace ast
     358        };
     359};
     360};
  • src/AST/Print.cpp

    rfb0ae06 rdab09ad  
    2929
    3030template <typename C, typename... T>
    31 constexpr array<C,sizeof...(T)> make_array(T&&... values)
     31constexpr auto make_array(T&&... values) ->
     32        array<C,sizeof...(T)>
    3233{
    3334        return array<C,sizeof...(T)>{
     
    128129
    129130        void print( const ast::Expr::InferUnion & inferred, unsigned level = 0 ) {
    130                 if (inferred.data.resnSlots && !inferred.data.resnSlots->empty()) {
    131                         os << indent << "with " << inferred.data.resnSlots->size()
     131                switch ( inferred.mode ) {
     132                case ast::Expr::InferUnion::Empty: return;
     133                case ast::Expr::InferUnion::Slots: {
     134                        os << indent << "with " << inferred.data.resnSlots.size()
    132135                           << " pending inference slots" << endl;
    133                 }
    134                 if (inferred.data.inferParams && !inferred.data.inferParams->empty()) {
     136                        return;
     137                }
     138                case ast::Expr::InferUnion::Params: {
    135139                        os << indent << "with inferred parameters " << level << ":" << endl;
    136140                        ++indent;
    137                         for ( const auto & i : *inferred.data.inferParams ) {
     141                        for ( const auto & i : inferred.data.inferParams ) {
    138142                                os << indent;
    139                                 short_print( i.second.declptr );
     143                                short_print( Decl::fromId( i.second.decl ) );
    140144                                os << endl;
    141145                                print( i.second.expr->inferred, level+1 );
    142146                        }
    143147                        --indent;
     148                        return;
     149                }
    144150                }
    145151        }
     
    227233                }
    228234
    229                 if ( ! node->assertions.empty() ) {
     235                if ( ! short_mode && ! node->assertions.empty() ) {
    230236                        os << endl << indent << "... with assertions" << endl;
    231237                        ++indent;
     
    836842        virtual const ast::Expr * visit( const ast::CastExpr * node ) override final {
    837843                ++indent;
    838                 os << (node->isGenerated ? "Generated" : "Explicit") << " Cast of:" << endl << indent;
     844                os << (node->isGenerated ? "Generated" : "Explicit") << " cast of:" << endl << indent;
    839845                safe_print( node->arg );
    840846                os << endl << indent-1 << "... to:";
  • src/AST/Stmt.hpp

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    99// Author           : Aaron B. Moss
    1010// Created On       : Mon May 13 15:00:00 2019
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Jul 23 14:16:00 2020
    13 // Update Count     : 5
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sun Dec 15 16:56:28 2019
     13// Update Count     : 4
    1414//
    1515
     
    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.core( 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.core( o.returns ); // apply to return and parameter types
    110         params = sub.core( 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.core( 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" );
     
    148116}
    149117
    150 // --- SueInstType (StructInstType, UnionInstType, EnumInstType)
     118// --- StructInstType
    151119
    152 template<typename decl_t>
    153 SueInstType<decl_t>::SueInstType(
    154         const decl_t * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
    155 : 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 ) {}
    156123
    157 template<typename decl_t>
    158 bool SueInstType<decl_t>::isComplete() const {
    159         return base ? base->body : false;
    160 }
     124bool StructInstType::isComplete() const { return base ? base->body : false; }
    161125
    162 template class SueInstType<StructDecl>;
    163 template class SueInstType<UnionDecl>;
    164 template class SueInstType<EnumDecl>;
     126// --- UnionInstType
     127
     128UnionInstType::UnionInstType( const UnionDecl * b, CV::Qualifiers q,
     129        std::vector<ptr<Attribute>>&& as )
     130: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     131
     132bool UnionInstType::isComplete() const { return base ? base->body : false; }
     133
     134// --- EnumInstType
     135
     136EnumInstType::EnumInstType( const EnumDecl * b, CV::Qualifiers q,
     137        std::vector<ptr<Attribute>>&& as )
     138: ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     139
     140bool EnumInstType::isComplete() const { return base ? base->body : false; }
    165141
    166142// --- TraitInstType
    167143
    168 TraitInstType::TraitInstType(
    169         const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
    170 : 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 ) {}
    171147
    172148// --- TypeInstType
    173 
    174 TypeInstType::TypeInstType( const TypeInstType & o )
    175 : ReferenceToType( o.name, o.qualifiers, copy( o.attributes ) ), base(), kind( o.kind ) {
    176         Pass< ForallSubstitutor > sub;
    177         initWithSub( o, sub );      // initialize substitution
    178         base = sub.core( o.base );  // apply to base type
    179 }
    180149
    181150void TypeInstType::set_base( const TypeDecl * b ) {
     
    189158
    190159TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q )
    191 : Type( q ), types( move(ts) ), members() {
     160: Type( q ), types( std::move(ts) ), members() {
    192161        // This constructor is awkward. `TupleType` needs to contain objects so that members can be
    193162        // named, but members without initializer nodes end up getting constructors, which breaks
  • src/AST/Type.hpp

    rfb0ae06 rdab09ad  
    99// Author           : Aaron B. Moss
    1010// Created On       : Thu May 9 10:00:00 2019
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Jul 23 14:15:00 2020
    13 // Update Count     : 6
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Dec 11 21:56:46 2019
     13// Update Count     : 5
    1414//
    1515
     
    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
     
    354333};
    355334
    356 // Common implementation for the SUE instance types. Not to be used directly.
    357 template<typename decl_t>
    358 class SueInstType final : public ReferenceToType {
    359 public:
    360         using base_type = decl_t;
    361         readonly<decl_t> base;
    362 
    363         SueInstType(
    364                 const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
     335/// instance of struct type
     336class StructInstType final : public ReferenceToType {
     337public:
     338        readonly<StructDecl> base;
     339
     340        StructInstType( const std::string& n, CV::Qualifiers q = {},
     341                std::vector<ptr<Attribute>> && as = {} )
    365342        : ReferenceToType( n, q, std::move(as) ), base() {}
    366 
    367         SueInstType(
    368                 const decl_t * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
     343        StructInstType( const StructDecl * b, CV::Qualifiers q = {},
     344                std::vector<ptr<Attribute>> && as = {} );
    369345
    370346        bool isComplete() const override;
    371347
    372         const decl_t * aggr() const override { return base; }
    373 
    374         const Type * accept( Visitor & v ) const override { return v.visit( this ); }
    375 private:
    376         SueInstType<decl_t> * clone() const override { return new SueInstType<decl_t>{ *this }; }
    377         MUTATE_FRIEND
    378 };
    379 
    380 /// An instance of a struct type.
    381 using StructInstType = SueInstType<StructDecl>;
    382 
    383 /// An instance of a union type.
    384 using UnionInstType = SueInstType<UnionDecl>;
    385 
    386 /// An instance of an enum type.
    387 using EnumInstType = SueInstType<EnumDecl>;
    388 
    389 /// An instance of a trait type.
     348        const StructDecl * aggr() const override { return base; }
     349
     350        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     351private:
     352        StructInstType * clone() const override { return new StructInstType{ *this }; }
     353        MUTATE_FRIEND
     354};
     355
     356/// instance of union type
     357class UnionInstType final : public ReferenceToType {
     358public:
     359        readonly<UnionDecl> base;
     360
     361        UnionInstType( const std::string& n, CV::Qualifiers q = {},
     362                std::vector<ptr<Attribute>> && as = {} )
     363        : ReferenceToType( n, q, std::move(as) ), base() {}
     364        UnionInstType( const UnionDecl * b, CV::Qualifiers q = {},
     365                std::vector<ptr<Attribute>> && as = {} );
     366
     367        bool isComplete() const override;
     368
     369        const UnionDecl * aggr() const override { return base; }
     370
     371        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     372private:
     373        UnionInstType * clone() const override { return new UnionInstType{ *this }; }
     374        MUTATE_FRIEND
     375};
     376
     377/// instance of enum type
     378class EnumInstType final : public ReferenceToType {
     379public:
     380        readonly<EnumDecl> base;
     381
     382        EnumInstType( const std::string& n, CV::Qualifiers q = {},
     383                std::vector<ptr<Attribute>> && as = {} )
     384        : ReferenceToType( n, q, std::move(as) ), base() {}
     385        EnumInstType( const EnumDecl * b, CV::Qualifiers q = {},
     386                std::vector<ptr<Attribute>> && as = {} );
     387
     388        bool isComplete() const override;
     389
     390        const EnumDecl * aggr() const override { return base; }
     391
     392        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     393private:
     394        EnumInstType * clone() const override { return new EnumInstType{ *this }; }
     395        MUTATE_FRIEND
     396};
     397
     398/// instance of trait type
    390399class TraitInstType final : public ReferenceToType {
    391400public:
    392401        readonly<TraitDecl> base;
    393402
    394         TraitInstType(
    395                 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 = {} )
    396405        : ReferenceToType( n, q, std::move(as) ), base() {}
    397 
    398         TraitInstType(
    399                 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 = {} );
    400408
    401409        // not meaningful for TraitInstType
     
    416424        TypeDecl::Kind kind;
    417425
    418         TypeInstType(
    419                 const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
     426        TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
    420427                std::vector<ptr<Attribute>> && as = {} )
    421428        : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
     
    423430                std::vector<ptr<Attribute>> && as = {} )
    424431        : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
    425 
    426         TypeInstType( const TypeInstType & o );
    427432
    428433        /// sets `base`, updating `kind` correctly
  • src/AST/TypeEnvironment.cpp

    rfb0ae06 rdab09ad  
    5959        std::copy( clz.vars.begin(), clz.vars.end(), std::ostream_iterator< std::string >( out, " " ) );
    6060        out << ")";
    61 
     61       
    6262        if ( clz.bound ) {
    6363                out << " -> ";
     
    9292                                }
    9393                        }
    94 
     94                       
    9595                        i = next;  // go to next node even if this removed
    9696                }
     
    161161                Pass<Occurs> occur{ var, env };
    162162                maybe_accept( ty, occur );
    163                 return occur.core.result;
    164         }
    165 }
    166 
    167 bool TypeEnvironment::combine(
     163                return occur.pass.result;
     164        }
     165}
     166
     167bool TypeEnvironment::combine( 
    168168                const TypeEnvironment & o, OpenVarSet & open, const SymbolTable & symtab ) {
    169169        // short-circuit easy cases
     
    199199                                auto st = internal_lookup( *vt );
    200200                                if ( st == env.end() ) {
    201                                         // unbound, safe to add if occurs
     201                                        // unbound, safe to add if occurs 
    202202                                        if ( r.bound && occurs( r.bound, *vt, *this ) ) return false;
    203203                                        r.vars.emplace( *vt );
     
    266266}
    267267
    268 bool TypeEnvironment::bindVar(
    269                 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data,
    270                 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen,
    271                 const SymbolTable & symtab
     268bool TypeEnvironment::bindVar( 
     269                const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 
     270                AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen, 
     271                const SymbolTable & symtab 
    272272) {
    273273        // remove references from bound type, so that type variables can only bind to value types
     
    286286                        ptr<Type> newType = it->bound;
    287287                        reset_qualifiers( newType, typeInst->qualifiers );
    288                         if ( unifyInexact(
    289                                         newType, target, *this, need, have, open,
     288                        if ( unifyInexact( 
     289                                        newType, target, *this, need, have, open, 
    290290                                        widen & WidenMode{ it->allowWidening, true }, symtab, common ) ) {
    291291                                if ( common ) {
     
    300300                }
    301301        } else {
    302                 env.emplace_back(
     302                env.emplace_back( 
    303303                        typeInst->name, target, widen.first && widen.second, data );
    304304        }
     
    306306}
    307307
    308 bool TypeEnvironment::bindVarToVar(
    309                 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data,
    310                 AssertionSet & need, AssertionSet & have, const OpenVarSet & open,
    311                 WidenMode widen, const SymbolTable & symtab
     308bool TypeEnvironment::bindVarToVar( 
     309                const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 
     310                AssertionSet & need, AssertionSet & have, const OpenVarSet & open, 
     311                WidenMode widen, const SymbolTable & symtab 
    312312) {
    313313        auto c1 = internal_lookup( var1->name );
    314314        auto c2 = internal_lookup( var2->name );
    315 
     315       
    316316        // exit early if variables already bound together
    317317        if ( c1 != env.end() && c1 == c2 ) {
     
    396396}
    397397
    398 bool TypeEnvironment::mergeBound(
     398bool TypeEnvironment::mergeBound( 
    399399                EqvClass & to, const EqvClass & from, OpenVarSet & open, const SymbolTable & symtab ) {
    400400        if ( from.bound ) {
     
    406406                        AssertionSet need, have;
    407407
    408                         if ( unifyInexact(
     408                        if ( unifyInexact( 
    409409                                        toType, fromType, *this, need, have, open, widen, symtab, common ) ) {
    410410                                // unifies, set common type if necessary
     
    424424}
    425425
    426 bool TypeEnvironment::mergeClasses(
     426bool TypeEnvironment::mergeClasses( 
    427427        ClassList::iterator to, ClassList::iterator from, OpenVarSet & open, const SymbolTable & symtab
    428428) {
  • src/AST/TypeEnvironment.hpp

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    1818
    1919namespace ast {
    20 
    21 
    22 // size_t TypeSubstitution::Substituter::traceId = Stats::Heap::new_stacktrace_id("TypeSubstitution");
    2320
    2421TypeSubstitution::TypeSubstitution() {
     
    9592namespace {
    9693        struct EnvTrimmer {
    97                 const TypeSubstitution * env;
     94                ptr<TypeSubstitution> env;
    9895                TypeSubstitution * newEnv;
    9996                EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
     
    111108        if ( env ) {
    112109                TypeSubstitution * newEnv = new TypeSubstitution();
     110#if TIME_TO_CONVERT_PASSES
    113111                Pass<EnvTrimmer> trimmer( env, newEnv );
    114112                expr->accept( trimmer );
     113#else
     114                (void)expr;
     115                (void)env;
     116#endif
    115117                return newEnv;
    116118        }
     
    119121
    120122void TypeSubstitution::normalize() {
    121         Pass<Substituter> sub( *this, true );
     123#if TIME_TO_CONVERT_PASSES
     124        PassVisitor<Substituter> sub( *this, true );
    122125        do {
    123                 sub.core.subCount = 0;
    124                 sub.core.freeOnly = true;
     126                sub.pass.subCount = 0;
     127                sub.pass.freeOnly = true;
    125128                for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
    126                         i->second = i->second->accept( sub );
     129                        i->second = i->second->acceptMutator( sub );
    127130                }
    128         } while ( sub.core.subCount );
    129 }
    130 
    131 const Type * TypeSubstitution::Substituter::postvisit( const TypeInstType *inst ) {
     131        } while ( sub.pass.subCount );
     132#endif
     133}
     134
     135#if TIME_TO_CONVERT_PASSES
     136
     137Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) {
    132138        BoundVarsType::const_iterator bound = boundVars.find( inst->name );
    133139        if ( bound != boundVars.end() ) return inst;
     
    140146                // Note: this does not prevent cycles in the general case, so it may be necessary to do something more sophisticated here.
    141147                // TODO: investigate preventing type variables from being bound to themselves in the first place.
    142                 if ( const TypeInstType * replacement = i->second.as<TypeInstType>() ) {
     148                if ( TypeInstType * replacement = i->second.as<TypeInstType>() ) {
    143149                        if ( inst->name == replacement->name ) {
    144150                                return inst;
     
    147153                // std::cerr << "found " << inst->name << ", replacing with " << i->second << std::endl;
    148154                subCount++;
    149                 ptr<Type> newType = i->second; // force clone if needed
    150                 add_qualifiers( newType, inst->qualifiers );
    151                 // Note: need to recursively apply substitution to the new type because normalize does not
    152                 // substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
    153                 newType = newType->accept( *visitor );
    154                 return newType.release();
    155         } // if
    156 }
    157 
    158 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 ) {
    159164        VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name );
    160165        if ( i == sub.varEnv.end() ) {
     
    162167        } else {
    163168                subCount++;
    164                 return i->second;
    165         } // if
    166 }
    167 
    168 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 ) {
    169175        GuardValue( boundVars );
    170176        // bind type variables from forall-qualifiers
    171177        if ( freeOnly ) {
    172                 for ( const TypeDecl * tyvar : ptype->forall ) {
    173                                 boundVars.insert( tyvar->name );
     178                for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
     179                        boundVars.insert( (*tyvar)->name );
    174180                } // for
    175181        } // if
    176182}
    177183
    178 void TypeSubstitution::Substituter::handleAggregateType( const ReferenceToType * type ) {
     184template< typename TypeClass >
     185void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) {
    179186        GuardValue( boundVars );
    180187        // bind type variables from forall-qualifiers
    181188        if ( freeOnly ) {
    182                 for ( const TypeDecl * tyvar : type->forall ) {
    183                         boundVars.insert( tyvar->name );
     189                for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
     190                        boundVars.insert( (*tyvar)->name );
    184191                } // for
    185192                // bind type variables from generic type instantiations
    186                 if ( auto decl = type->aggr() ) {
    187                         if ( ! type->params.empty() ) {
    188                                 for ( const TypeDecl * tyvar : decl->params ) {
    189                                         boundVars.insert( tyvar->name );
    190                                 } // for
    191                         } // if
    192                 }
    193         } // if
    194 }
    195 
    196 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 ) {
    197203        handleAggregateType( aggregateUseType );
    198204}
    199205
    200 void TypeSubstitution::Substituter::previsit( const UnionInstType *aggregateUseType ) {
     206void TypeSubstitution::Substituter::premutate( UnionInstType *aggregateUseType ) {
    201207        handleAggregateType( aggregateUseType );
    202208}
     209
     210#endif
    203211
    204212} // namespace ast
  • src/AST/TypeSubstitution.hpp

    rfb0ae06 rdab09ad  
    4444        TypeSubstitution &operator=( const TypeSubstitution &other );
    4545
    46         template< typename SynTreeClass >
    47         struct ApplyResult {
    48                 // const SynTreeClass * node;
    49                 ast::ptr<SynTreeClass> node;
    50                 int count;
    51         };
    52 
    53         template< typename SynTreeClass > ApplyResult<SynTreeClass> apply( const SynTreeClass * input ) const;
    54         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;
    5548
    5649        template< typename node_t, enum Node::ref_type ref_t >
    5750        int apply( ptr_base< node_t, ref_t > & input ) const {
    5851                const node_t * p = input.get();
    59                 auto ret = apply(p);
    60                 input = ret.node;
    61                 return ret.count;
     52                int ret = apply(p);
     53                input = p;
     54                return ret;
    6255        }
    6356
     
    6558        int applyFree( ptr_base< node_t, ref_t > & input ) const {
    6659                const node_t * p = input.get();
    67                 auto ret = applyFree(p);
    68                 input = ret.node;
    69                 return ret.count;
     60                int ret = applyFree(p);
     61                input = p;
     62                return ret;
    7063        }
    7164
     
    9992        void initialize( const TypeSubstitution &src, TypeSubstitution &dest );
    10093
    101         template<typename core_t>
     94        template<typename pass_type>
    10295        friend class Pass;
    10396
     
    154147// PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals.
    155148#include "Pass.hpp"
    156 #include "Copy.hpp"
    157149
    158150namespace ast {
     
    160152// definitition must happen after PassVisitor is included so that WithGuards can be used
    161153struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter> {
    162                 static size_t traceId;
    163154
    164155                Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
    165156
    166                 const Type * postvisit( const TypeInstType * aggregateUseType );
    167                 const Expr * postvisit( const NameExpr * nameExpr );
     157#if TIME_TO_CONVERT_PASSES
     158
     159                Type * postmutate( TypeInstType * aggregateUseType );
     160                Expression * postmutate( NameExpr * nameExpr );
    168161
    169162                /// Records type variable bindings from forall-statements
    170                 void previsit( const ParameterizedType * type );
     163                void premutate( Type * type );
    171164                /// Records type variable bindings from forall-statements and instantiations of generic types
    172                 void handleAggregateType( const ReferenceToType * type );
    173 
    174                 void previsit( const StructInstType * aggregateUseType );
    175                 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
    176171
    177172                const TypeSubstitution & sub;
     
    184179
    185180template< typename SynTreeClass >
    186 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::apply( const SynTreeClass * input ) const {
     181int TypeSubstitution::apply( const SynTreeClass *& input ) const {
    187182        assert( input );
    188183        Pass<Substituter> sub( *this, false );
    189         input = strict_dynamic_cast< const SynTreeClass * >( deepCopy(input)->accept( sub ) );
    190         return { input, sub.core.subCount };
     184        input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
     185///     std::cerr << "substitution result is: ";
     186///     newType->print( std::cerr );
     187///     std::cerr << std::endl;
     188        return sub.pass.subCount;
    191189}
    192190
    193191template< typename SynTreeClass >
    194 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::applyFree( const SynTreeClass * input ) const {
     192int TypeSubstitution::applyFree( const SynTreeClass *& input ) const {
    195193        assert( input );
    196194        Pass<Substituter> sub( *this, true );
    197195        input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
    198         return { input, sub.core.subCount };
     196///     std::cerr << "substitution result is: ";
     197///     newType->print( std::cerr );
     198///     std::cerr << std::endl;
     199        return sub.pass.subCount;
    199200}
    200201
  • src/AST/module.mk

    rfb0ae06 rdab09ad  
    2222        AST/DeclReplacer.cpp \
    2323        AST/Expr.cpp \
    24         AST/ForallSubstitutionTable.cpp \
    2524        AST/GenericSubstitution.cpp \
    2625        AST/Init.cpp \
  • src/AST/porting.md

    rfb0ae06 rdab09ad  
    4747      template<typename node_t>
    4848      friend node_t * mutate(const node_t * node);
    49       template<typename node_t>
    50       friend node_t * shallowCopy(const node_t * node);
    51     or equilant.
    52 * You should use the `mutate` function where possible as it avoids extra copies.
    53   * If you must copy use `shallowCopy` or `deepCopy` as required.
    5449
    5550All leaves of the `Node` inheritance tree are now declared `final`
  • src/Common/Eval.cc

    rfb0ae06 rdab09ad  
    168168        if (expr) {
    169169                expr->accept(ev);
    170                 return std::make_pair(ev.core.value, ev.core.valid);
     170                return std::make_pair(ev.pass.value, ev.pass.valid);
    171171        } else {
    172172                return std::make_pair(0, false);
  • src/Common/ScopedMap.h

    rfb0ae06 rdab09ad  
    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/Common/Stats/Heap.cc

    rfb0ae06 rdab09ad  
    5353                const size_t passes_size = sizeof(passes) / sizeof(passes[0]);
    5454                size_t       passes_cnt = 1;
    55 
    56                 StatBlock    stacktrace_stats[100];
    57                 size_t       stacktrace_stats_count = 0;
    58                 bool         stacktrace_stats_enabled = true;
    59 
    60                 size_t       trace[1000];
    61                 const size_t stacktrace_max_depth = sizeof(trace) / sizeof(size_t);
    62                 size_t       stacktrace_depth;
    63 
    64                 size_t new_stacktrace_id(const char * const name) {
    65                         stacktrace_stats[stacktrace_stats_count].name = name;
    66                         return stacktrace_stats_count++;
    67                 }
    68 
    69                 void stacktrace_push(size_t id) {
    70                         ++stacktrace_depth;
    71                         assertf(stacktrace_depth < stacktrace_max_depth, "Stack trace too deep: increase size of array in Heap.cc");
    72                         trace[stacktrace_depth] = id;
    73                 }
    74 
    75                 void stacktrace_pop() {
    76                         assertf(stacktrace_depth > 0, "Invalid stack tracing operation: trace is empty");
    77                         --stacktrace_depth;
    78                 }
    7955
    8056                void newPass( const char * const name ) {
     
    140116                        for(size_t i = 0; i < passes_cnt; i++) {
    141117                                print(passes[i], nc, total_mallocs, total_frees, overall_peak);
    142                         }
    143 
    144                         print('-', nct);
    145                         std::cerr << std::setw(nc) << "Trace";
    146                         std::cerr << " |       Malloc Count |         Free Count |        Peak Allocs |" << std::endl;
    147 
    148                         print('-', nct);
    149                         for (size_t i = 0; i < stacktrace_stats_count; i++) {
    150                                 print(stacktrace_stats[i], nc, total_mallocs, total_frees, overall_peak);
    151118                        }
    152119                        print('-', nct);
     
    221188                                                = std::max(passes[passes_cnt - 1].peak_allocs, passes[passes_cnt - 1].n_allocs);
    222189                                }
    223 
    224                                 if ( stacktrace_stats_enabled && stacktrace_depth > 0) {
    225                                         stacktrace_stats[trace[stacktrace_depth]].mallocs++;
    226                                 }
    227190                                return __malloc( size );
    228191                        }
     
    233196                                        passes[passes_cnt - 1].frees++;
    234197                                        passes[passes_cnt - 1].n_allocs--;
    235                                 }
    236                                 if ( stacktrace_stats_enabled && stacktrace_depth > 0) {
    237                                         stacktrace_stats[trace[stacktrace_depth]].frees++;
    238198                                }
    239199                                return __free( ptr );
     
    248208                                                = std::max(passes[passes_cnt - 1].peak_allocs, passes[passes_cnt - 1].n_allocs);
    249209                                }
    250                                 if ( stacktrace_stats_enabled && stacktrace_depth > 0) {
    251                                         stacktrace_stats[trace[stacktrace_depth]].mallocs++;
    252                                 }
    253210                                return __calloc( nelem, size );
    254211                        }
     
    261218                                        passes[passes_cnt - 1].frees++;
    262219                                } // if
    263                                 if ( stacktrace_stats_enabled && stacktrace_depth > 0) {
    264                                         stacktrace_stats[trace[stacktrace_depth]].mallocs++;
    265                                         stacktrace_stats[trace[stacktrace_depth]].frees++;
    266                                 }
    267220                                return s;
    268221                        }
  • src/Common/Stats/Heap.h

    rfb0ae06 rdab09ad  
    2020                void newPass( const char * const name );
    2121                void print();
    22 
    23                 size_t new_stacktrace_id(const char * const name);
    24                 void stacktrace_push(size_t id);
    25                 void stacktrace_pop();
    2622        }
    2723}
  • src/CompilationState.cc

    rfb0ae06 rdab09ad  
    1414//
    1515
    16 #include "config.h"
    17 
    1816int
    1917        astp = false,
     
    3028        genproto = false,
    3129        deterministic_output = false,
    32         useNewAST = CFA_USE_NEW_AST,
    3330        nomainp = false,
    3431        parsep = false,
  • src/CompilationState.h

    rfb0ae06 rdab09ad  
    2929        genproto,
    3030        deterministic_output,
    31         useNewAST,
    3231        nomainp,
    3332        parsep,
  • src/InitTweak/InitTweak.cc

    rfb0ae06 rdab09ad  
    127127        ast::Pass< InitFlattener_new > flattener;
    128128        maybe_accept( init, flattener );
    129         return std::move( flattener.core.argList );
     129        return std::move( flattener.pass.argList );
    130130}
    131131
     
    561561                ast::Pass< CallFinder_new > finder{ std::vector< std::string >{ "?{}", "^?{}" } };
    562562                maybe_accept( stmt, finder );
    563                 return std::move( finder.core.matches );
     563                return std::move( finder.pass.matches );
    564564        }
    565565
  • src/ResolvExpr/AdjustExprType.cc

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    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                 static size_t traceId;
    599                 CandidateFinder & selfFinder;
    600599                CandidateList & candidates;
    601600                const ast::TypeEnvironment & tenv;
    602601                ast::ptr< ast::Type > & targetType;
    603602
    604                 enum Errors {
    605                         NotFound,
    606                         NoMatch,
    607                         ArgsToFew,
    608                         ArgsToMany,
    609                         RetsToFew,
    610                         RetsToMany,
    611                         NoReason
    612                 };
    613 
    614                 struct {
    615                         Errors code = NotFound;
    616                 } reason;
    617 
    618603                Finder( CandidateFinder & f )
    619                 : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
     604                : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
    620605                  targetType( f.targetType ) {}
    621 
     606               
    622607                void previsit( const ast::Node * ) { visit_children = false; }
    623608
     
    626611                void addCandidate( Args &&... args ) {
    627612                        candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } );
    628                         reason.code = NoReason;
    629613                }
    630614
     
    655639
    656640                /// Completes a function candidate with arguments located
    657                 void validateFunctionCandidate(
    658                         const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,
    659                         CandidateList & out
     641                void validateFunctionCandidate( 
     642                        const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 
     643                        CandidateList & out 
    660644                ) {
    661                         ast::ApplicationExpr * appExpr =
     645                        ast::ApplicationExpr * appExpr = 
    662646                                new ast::ApplicationExpr{ func->expr->location, func->expr };
    663647                        // sum cost and accumulate arguments
     
    673657                        appExpr->args = move( vargs );
    674658                        // build and validate new candidate
    675                         auto newCand =
     659                        auto newCand = 
    676660                                std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );
    677661                        PRINT(
     
    685669                /// Builds a list of candidates for a function, storing them in out
    686670                void makeFunctionCandidates(
    687                         const CandidateRef & func, const ast::FunctionType * funcType,
     671                        const CandidateRef & func, const ast::FunctionType * funcType, 
    688672                        const ExplodedArgs_new & args, CandidateList & out
    689673                ) {
     
    692676                        ast::TypeEnvironment funcEnv{ func->env };
    693677                        makeUnifiableVars( funcType, funcOpen, funcNeed );
    694                         // add all type variables as open variables now so that those not used in the
    695                         // 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
    696680                        funcEnv.add( funcType->forall );
    697681
     
    699683                                // attempt to narrow based on expected target type
    700684                                const ast::Type * returnType = funcType->returns.front()->get_type();
    701                                 if ( ! unify(
    702                                         returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
     685                                if ( ! unify( 
     686                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 
    703687                                ) {
    704688                                        // unification failed, do not pursue this candidate
     
    714698                        for ( const ast::DeclWithType * param : funcType->params ) {
    715699                                auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
    716                                 // 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 
    717701                                // matches
    718                                 if ( ! instantiateArgument(
     702                                if ( ! instantiateArgument( 
    719703                                        obj->type, obj->init, args, results, genStart, symtab ) ) return;
    720704                        }
     
    766750                                                        if ( expl.exprs.empty() ) {
    767751                                                                results.emplace_back(
    768                                                                         results[i], move( env ), copy( results[i].need ),
    769                                                                         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, 
    770754                                                                        expl.cost );
    771755
     
    776760                                                        results.emplace_back(
    777761                                                                i, expl.exprs.front(), move( env ), copy( results[i].need ),
    778                                                                 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost,
     762                                                                copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 
    779763                                                                expl.exprs.size() == 1 ? 0 : 1, j );
    780764                                                }
     
    796780                /// Adds implicit struct-conversions to the alternative list
    797781                void addAnonConversions( const CandidateRef & cand ) {
    798                         // adds anonymous member interpretations whenever an aggregate value type is seen.
    799                         // 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 
    800784                        // base type to treat the aggregate as the referenced value
    801785                        ast::ptr< ast::Expr > aggrExpr( cand->expr );
    802786                        ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;
    803787                        cand->env.apply( aggrType );
    804 
     788                       
    805789                        if ( aggrType.as< ast::ReferenceType >() ) {
    806790                                aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };
     
    815799
    816800                /// Adds aggregate member interpretations
    817                 void addAggMembers(
    818                         const ast::ReferenceToType * aggrInst, const ast::Expr * expr,
    819                         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 
    820804                ) {
    821805                        for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {
    822806                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );
    823                                 CandidateRef newCand = std::make_shared<Candidate>(
     807                                CandidateRef newCand = std::make_shared<Candidate>( 
    824808                                        cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
    825                                 // add anonymous member interpretations whenever an aggregate value type is seen
     809                                // add anonymous member interpretations whenever an aggregate value type is seen 
    826810                                // as a member expression
    827811                                addAnonConversions( newCand );
     
    831815
    832816                /// Adds tuple member interpretations
    833                 void addTupleMembers(
    834                         const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,
    835                         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 
    836820                ) {
    837821                        if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) {
    838                                 // 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 
    839823                                // length of the tuple to have meaning
    840824                                long long val = constantExpr->intValue();
    841825                                if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    842826                                        addCandidate(
    843                                                 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },
     827                                                cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 
    844828                                                addedCost );
    845829                                }
     
    853837                        if ( funcFinder.candidates.empty() ) return;
    854838
    855                         reason.code = NoMatch;
    856 
    857                         std::vector< CandidateFinder > argCandidates =
     839                        std::vector< CandidateFinder > argCandidates =
    858840                                selfFinder.findSubExprs( untypedExpr->args );
    859 
     841                       
    860842                        // take care of possible tuple assignments
    861843                        // if not tuple assignment, handled as normal function call
     
    895877                                                if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    896878                                                        CandidateRef newFunc{ new Candidate{ *func } };
    897                                                         newFunc->expr =
     879                                                        newFunc->expr = 
    898880                                                                referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    899881                                                        makeFunctionCandidates( newFunc, function, argExpansions, found );
    900882                                                }
    901                                         } else if (
    902                                                 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
     883                                        } else if ( 
     884                                                auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 
    903885                                        ) {
    904886                                                if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) {
    905887                                                        if ( auto function = clz->bound.as< ast::FunctionType >() ) {
    906888                                                                CandidateRef newFunc{ new Candidate{ *func } };
    907                                                                 newFunc->expr =
     889                                                                newFunc->expr = 
    908890                                                                        referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    909891                                                                makeFunctionCandidates( newFunc, function, argExpansions, found );
     
    919901                                std::vector< ExplodedArg > funcE;
    920902                                funcE.reserve( funcFinder.candidates.size() );
    921                                 for ( const CandidateRef & func : funcFinder ) {
     903                                for ( const CandidateRef & func : funcFinder ) { 
    922904                                        funcE.emplace_back( *func, symtab );
    923905                                }
     
    931913                                                        if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    932914                                                                CandidateRef newOp{ new Candidate{ *op} };
    933                                                                 newOp->expr =
     915                                                                newOp->expr = 
    934916                                                                        referenceToRvalueConversion( newOp->expr, newOp->cost );
    935917                                                                makeFunctionCandidates( newOp, function, argExpansions, found );
     
    940922                        }
    941923
    942                         // 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 
    943925                        // candidates
    944926                        if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
     
    952934                                        auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
    953935                                        auto function = pointer->base.strict_as< ast::FunctionType >();
    954 
     936                                       
    955937                                        std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;
    956938                                        std::cerr << "parameters are:" << std::endl;
     
    975957                        promoteCvtCost( winners );
    976958
    977                         // function may return a struct/union value, in which case we need to add candidates
    978                         // 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 
    979961                        // `findMinCost`, since anon conversions are never the cheapest
    980962                        for ( const CandidateRef & c : winners ) {
     
    984966
    985967                        if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
    986                                 // 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 
    987969                                // will sometimes succeed when it wouldn't with a target type binding.
    988970                                // For example:
     
    1001983                /// true if expression is an lvalue
    1002984                static bool isLvalue( const ast::Expr * x ) {
    1003                         return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() );
     985                        return x->result && ( x->result->is_lvalue() || x->result.as< ast::ReferenceType >() );
    1004986                }
    1005987
     
    1007989                        CandidateFinder finder{ symtab, tenv };
    1008990                        finder.find( addressExpr->arg );
    1009 
    1010                         if( finder.candidates.empty() ) return;
    1011 
    1012                         reason.code = NoMatch;
    1013 
    1014991                        for ( CandidateRef & r : finder.candidates ) {
    1015992                                if ( ! isLvalue( r->expr ) ) continue;
     
    10321009                        finder.find( castExpr->arg, ResolvMode::withAdjustment() );
    10331010
    1034                         if( !finder.candidates.empty() ) reason.code = NoMatch;
    1035 
    10361011                        CandidateList matches;
    10371012                        for ( CandidateRef & cand : finder.candidates ) {
     
    10411016                                cand->env.extractOpenVars( open );
    10421017
    1043                                 // It is possible that a cast can throw away some values in a multiply-valued
    1044                                 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the
    1045                                 // 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 
    10461021                                // has fewer results than there are types to cast to.
    10471022                                int discardedValues = cand->expr->result->size() - toType->size();
     
    10501025                                // unification run for side-effects
    10511026                                unify( toType, cand->expr->result, cand->env, need, have, open, symtab );
    1052                                 Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
    1053                                                 symtab, cand->env );
     1027                                Cost thisCost = castCost( cand->expr->result, toType, symtab, cand->env );
    10541028                                PRINT(
    10551029                                        std::cerr << "working on cast with result: " << toType << std::endl;
     
    10631037                                        // count one safe conversion for each value that is thrown away
    10641038                                        thisCost.incSafe( discardedValues );
    1065                                         CandidateRef newCand = std::make_shared<Candidate>(
    1066                                                 restructureCast( cand->expr, toType, castExpr->isGenerated ),
    1067                                                 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, 
    10681042                                                cand->cost + thisCost );
    10691043                                        inferParameters( newCand, matches );
     
    10831057                        finder.find( castExpr->arg, ResolvMode::withoutPrune() );
    10841058                        for ( CandidateRef & r : finder.candidates ) {
    1085                                 addCandidate(
    1086                                         *r,
     1059                                addCandidate( 
     1060                                        *r, 
    10871061                                        new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
    10881062                        }
     
    10931067                        aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    10941068                        for ( CandidateRef & agg : aggFinder.candidates ) {
    1095                                 // 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 
    10961070                                // base type to treat the aggregate as the referenced value
    10971071                                Cost addedCost = Cost::zero;
     
    11001074                                // find member of the given type
    11011075                                if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {
    1102                                         addAggMembers(
     1076                                        addAggMembers( 
    11031077                                                structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    11041078                                } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {
    1105                                         addAggMembers(
     1079                                        addAggMembers( 
    11061080                                                unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    11071081                                } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {
     
    11181092                        std::vector< ast::SymbolTable::IdData > declList = symtab.lookupId( nameExpr->name );
    11191093                        PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
    1120                         if( declList.empty() ) return;
    1121 
    1122                         reason.code = NoMatch;
    1123 
    11241094                        for ( auto & data : declList ) {
    11251095                                Cost cost = Cost::zero;
     
    11271097
    11281098                                CandidateRef newCand = std::make_shared<Candidate>(
    1129                                         newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
     1099                                        newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 
    11301100                                        cost );
    11311101                                PRINT(
     
    11371107                                        std::cerr << std::endl;
    11381108                                )
    1139                                 newCand->expr = ast::mutate_field(
    1140                                         newCand->expr.get(), &ast::Expr::result,
     1109                                newCand->expr = ast::mutate_field( 
     1110                                        newCand->expr.get(), &ast::Expr::result, 
    11411111                                        renameTyVars( newCand->expr->result ) );
    1142                                 // add anonymous member interpretations whenever an aggregate value type is seen
     1112                                // add anonymous member interpretations whenever an aggregate value type is seen 
    11431113                                // as a name expression
    11441114                                addAnonConversions( newCand );
     
    11501120                        // not sufficient to just pass `variableExpr` here, type might have changed since
    11511121                        // creation
    1152                         addCandidate(
     1122                        addCandidate( 
    11531123                                new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
    11541124                }
     
    11601130                void postvisit( const ast::SizeofExpr * sizeofExpr ) {
    11611131                        if ( sizeofExpr->type ) {
    1162                                 addCandidate(
    1163                                         new ast::SizeofExpr{
    1164                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
     1132                                addCandidate( 
     1133                                        new ast::SizeofExpr{ 
     1134                                                sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 
    11651135                                        tenv );
    11661136                        } else {
     
    11711141                                CandidateList winners = findMinCost( finder.candidates );
    11721142                                if ( winners.size() != 1 ) {
    1173                                         SemanticError(
     1143                                        SemanticError( 
    11741144                                                sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );
    11751145                                }
     
    11841154                void postvisit( const ast::AlignofExpr * alignofExpr ) {
    11851155                        if ( alignofExpr->type ) {
    1186                                 addCandidate(
    1187                                         new ast::AlignofExpr{
    1188                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
     1156                                addCandidate( 
     1157                                        new ast::AlignofExpr{ 
     1158                                                alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 
    11891159                                        tenv );
    11901160                        } else {
     
    11951165                                CandidateList winners = findMinCost( finder.candidates );
    11961166                                if ( winners.size() != 1 ) {
    1197                                         SemanticError(
     1167                                        SemanticError( 
    11981168                                                alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );
    11991169                                }
     
    12021172                                choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    12031173                                choice->cost = Cost::zero;
    1204                                 addCandidate(
     1174                                addCandidate( 
    12051175                                        *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );
    12061176                        }
     
    12151185                        for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {
    12161186                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );
    1217                                 addCandidate(
     1187                                addCandidate( 
    12181188                                        new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );
    12191189                        }
     
    12361206                        finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );
    12371207                        if ( finder2.candidates.empty() ) return;
    1238 
    1239                         reason.code = NoMatch;
    12401208
    12411209                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    12501218
    12511219                                        addCandidate(
    1252                                                 new ast::LogicalExpr{
     1220                                                new ast::LogicalExpr{ 
    12531221                                                        logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
    12541222                                                move( env ), move( open ), move( need ), r1->cost + r2->cost );
     
    12721240                        finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );
    12731241                        if ( finder3.candidates.empty() ) return;
    1274 
    1275                         reason.code = NoMatch;
    12761242
    12771243                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    12901256                                                ast::AssertionSet have;
    12911257
    1292                                                 // unify true and false results, then infer parameters to produce new
     1258                                                // unify true and false results, then infer parameters to produce new 
    12931259                                                // candidates
    12941260                                                ast::ptr< ast::Type > common;
    1295                                                 if (
    1296                                                         unify(
    1297                                                                 r2->expr->result, r3->expr->result, env, need, have, open, symtab,
    1298                                                                 common )
     1261                                                if ( 
     1262                                                        unify( 
     1263                                                                r2->expr->result, r3->expr->result, env, need, have, open, symtab, 
     1264                                                                common ) 
    12991265                                                ) {
    13001266                                                        // generate typed expression
    1301                                                         ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{
     1267                                                        ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 
    13021268                                                                conditionalExpr->location, r1->expr, r2->expr, r3->expr };
    13031269                                                        newExpr->result = common ? common : r2->expr->result;
    13041270                                                        // convert both options to result type
    13051271                                                        Cost cost = r1->cost + r2->cost + r3->cost;
    1306                                                         newExpr->arg2 = computeExpressionConversionCost(
     1272                                                        newExpr->arg2 = computeExpressionConversionCost( 
    13071273                                                                newExpr->arg2, newExpr->result, symtab, env, cost );
    13081274                                                        newExpr->arg3 = computeExpressionConversionCost(
     
    13211287                        ast::TypeEnvironment env{ tenv };
    13221288                        ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
    1323 
     1289                       
    13241290                        CandidateFinder finder2{ symtab, env };
    13251291                        finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
     
    13511317                        finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );
    13521318                        if ( finder2.candidates.empty() ) return;
    1353 
    1354                         reason.code = NoMatch;
    13551319
    13561320                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    13661330
    13671331                                        ast::ptr< ast::Type > common;
    1368                                         if (
    1369                                                 unify(
    1370                                                         r1->expr->result, r2->expr->result, env, need, have, open, symtab,
    1371                                                         common )
     1332                                        if ( 
     1333                                                unify( 
     1334                                                        r1->expr->result, r2->expr->result, env, need, have, open, symtab, 
     1335                                                        common ) 
    13721336                                        ) {
    13731337                                                // generate new expression
    1374                                                 ast::RangeExpr * newExpr =
     1338                                                ast::RangeExpr * newExpr = 
    13751339                                                        new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
    13761340                                                newExpr->result = common ? common : r1->expr->result;
    13771341                                                // add candidate
    13781342                                                CandidateRef newCand = std::make_shared<Candidate>(
    1379                                                         newExpr, move( env ), move( open ), move( need ),
     1343                                                        newExpr, move( env ), move( open ), move( need ), 
    13801344                                                        r1->cost + r2->cost );
    13811345                                                inferParameters( newCand, candidates );
     
    13861350
    13871351                void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
    1388                         std::vector< CandidateFinder > subCandidates =
     1352                        std::vector< CandidateFinder > subCandidates = 
    13891353                                selfFinder.findSubExprs( tupleExpr->exprs );
    13901354                        std::vector< CandidateList > possibilities;
     
    14061370
    14071371                                addCandidate(
    1408                                         new ast::TupleExpr{ tupleExpr->location, move( exprs ) },
     1372                                        new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 
    14091373                                        move( env ), move( open ), move( need ), sumCost( subs ) );
    14101374                        }
     
    14481412                                toType = SymTab::validateType( initExpr->location, toType, symtab );
    14491413                                toType = adjustExprType( toType, tenv, symtab );
    1450                                 // The call to find must occur inside this loop, otherwise polymorphic return
    1451                                 // types are not bound to the initialization type, since return type variables are
    1452                                 // 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. 
    14531417                                CandidateFinder finder{ symtab, tenv, toType };
    14541418                                finder.find( initExpr->expr, ResolvMode::withAdjustment() );
    14551419                                for ( CandidateRef & cand : finder.candidates ) {
    1456                                         if(reason.code == NotFound) reason.code = NoMatch;
    1457 
    14581420                                        ast::TypeEnvironment env{ cand->env };
    14591421                                        ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;
     
    14641426                                        )
    14651427
    1466                                         // It is possible that a cast can throw away some values in a multiply-valued
    1467                                         // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of
    1468                                         // 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 
    14691431                                        // if it has fewer results than there are types to cast to.
    14701432                                        int discardedValues = cand->expr->result->size() - toType->size();
     
    14731435                                        // unification run for side-effects
    14741436                                        unify( toType, cand->expr->result, env, need, have, open, symtab );
    1475                                         Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
    1476                                                         symtab, env );
    1477 
     1437                                        Cost thisCost = castCost( cand->expr->result, toType, symtab, env );
     1438                                       
    14781439                                        if ( thisCost != Cost::infinity ) {
    14791440                                                // count one safe conversion for each value that is thrown away
    14801441                                                thisCost.incSafe( discardedValues );
    1481                                                 CandidateRef newCand = std::make_shared<Candidate>(
    1482                                                         new ast::InitExpr{
    1483                                                                 initExpr->location, restructureCast( cand->expr, toType ),
    1484                                                                 initAlt.designation },
     1442                                                CandidateRef newCand = std::make_shared<Candidate>( 
     1443                                                        new ast::InitExpr{ 
     1444                                                                initExpr->location, restructureCast( cand->expr, toType ), 
     1445                                                                initAlt.designation }, 
    14851446                                                        copy( cand->env ), move( open ), move( need ), cand->cost, thisCost );
    14861447                                                inferParameters( newCand, matches );
     
    15081469        };
    15091470
    1510         // size_t Finder::traceId = Stats::Heap::new_stacktrace_id("Finder");
    1511         /// 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
    15121472        /// return type. Skips ambiguous candidates.
    15131473        CandidateList pruneCandidates( CandidateList & candidates ) {
     
    15261486                        {
    15271487                                ast::ptr< ast::Type > newType = candidate->expr->result;
    1528                                 assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());
    15291488                                candidate->env.apply( newType );
    15301489                                mangleName = Mangle::mangle( newType );
     
    15351494                                if ( candidate->cost < found->second.candidate->cost ) {
    15361495                                        PRINT(
    1537                                                 std::cerr << "cost " << candidate->cost << " beats "
     1496                                                std::cerr << "cost " << candidate->cost << " beats " 
    15381497                                                        << found->second.candidate->cost << std::endl;
    15391498                                        )
     
    15411500                                        found->second = PruneStruct{ candidate };
    15421501                                } else if ( candidate->cost == found->second.candidate->cost ) {
    1543                                         // if one of the candidates contains a deleted identifier, can pick the other,
    1544                                         // 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 
    15451504                                        // that is at least as good
    15461505                                        if ( findDeletedExpr( candidate->expr ) ) {
     
    15561515                                } else {
    15571516                                        PRINT(
    1558                                                 std::cerr << "cost " << candidate->cost << " loses to "
     1517                                                std::cerr << "cost " << candidate->cost << " loses to " 
    15591518                                                        << found->second.candidate->cost << std::endl;
    15601519                                        )
     
    15711530
    15721531                        CandidateRef cand = target.second.candidate;
    1573 
     1532                       
    15741533                        ast::ptr< ast::Type > newResult = cand->expr->result;
    15751534                        cand->env.applyFree( newResult );
    15761535                        cand->expr = ast::mutate_field(
    15771536                                cand->expr.get(), &ast::Expr::result, move( newResult ) );
    1578 
     1537                       
    15791538                        out.emplace_back( cand );
    15801539                }
     
    15901549
    15911550        if ( mode.failFast && candidates.empty() ) {
    1592                 switch(finder.core.reason.code) {
    1593                 case Finder::NotFound:
    1594                         { SemanticError( expr, "No alternatives for expression " ); break; }
    1595                 case Finder::NoMatch:
    1596                         { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; }
    1597                 case Finder::ArgsToFew:
    1598                 case Finder::ArgsToMany:
    1599                 case Finder::RetsToFew:
    1600                 case Finder::RetsToMany:
    1601                 case Finder::NoReason:
    1602                 default:
    1603                         { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); }
    1604                 }
     1551                SemanticError( expr, "No reasonable alternatives for expression " );
    16051552        }
    16061553
     
    16111558                std::vector< std::string > errors;
    16121559                for ( CandidateRef & candidate : candidates ) {
    1613                         satisfyAssertions( candidate, localSyms, satisfied, errors );
     1560                        satisfyAssertions( candidate, symtab, satisfied, errors );
    16141561                }
    16151562
     
    16361583
    16371584                CandidateList pruned = pruneCandidates( candidates );
    1638 
     1585               
    16391586                if ( mode.failFast && pruned.empty() ) {
    16401587                        std::ostringstream stream;
     
    16551602                )
    16561603                PRINT(
    1657                         std::cerr << "there are " << candidates.size() << " alternatives after elimination"
     1604                        std::cerr << "there are " << candidates.size() << " alternatives after elimination" 
    16581605                                << std::endl;
    16591606                )
    16601607        }
    16611608
    1662         // 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 
    16631610        // adjusted
    16641611        if ( mode.adjust ) {
    16651612                for ( CandidateRef & r : candidates ) {
    1666                         r->expr = ast::mutate_field(
    1667                                 r->expr.get(), &ast::Expr::result,
    1668                                 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 ) );
    16691616                }
    16701617        }
     
    16781625}
    16791626
    1680 std::vector< CandidateFinder > CandidateFinder::findSubExprs(
    1681         const std::vector< ast::ptr< ast::Expr > > & xs
     1627std::vector< CandidateFinder > CandidateFinder::findSubExprs( 
     1628        const std::vector< ast::ptr< ast::Expr > > & xs 
    16821629) {
    16831630        std::vector< CandidateFinder > out;
    16841631
    16851632        for ( const auto & x : xs ) {
    1686                 out.emplace_back( localSyms, env );
     1633                out.emplace_back( symtab, env );
    16871634                out.back().find( x, ResolvMode::withAdjustment() );
    1688 
     1635               
    16891636                PRINT(
    16901637                        std::cerr << "findSubExprs" << std::endl;
  • src/ResolvExpr/CandidateFinder.hpp

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    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 );
    244                 return converter.core.cost;
     240                return converter.pass.cost;
    245241        }
    246242}
  • src/ResolvExpr/CommonType.cc

    rfb0ae06 rdab09ad  
    666666                const ast::OpenVarSet & open;
    667667        public:
    668                 static size_t traceId;
    669668                ast::ptr< ast::Type > result;
    670669
     
    894893        };
    895894
    896         // size_t CommonType_new::traceId = Stats::Heap::new_stacktrace_id("CommonType_new");
    897895        namespace {
    898896                ast::ptr< ast::Type > handleReference(
     
    941939                        ast::ptr< ast::Type > result;
    942940                        const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >();
    943                         const ast::ReferenceType * ref2 = type2.as< ast::ReferenceType >();
     941                        const ast::ReferenceType * ref2 = type1.as< ast::ReferenceType >();
    944942
    945943                        if ( depth1 > depth2 ) {
     
    968966                ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open };
    969967                type1->accept( visitor );
    970                 ast::ptr< ast::Type > result = visitor.core.result;
     968                ast::ptr< ast::Type > result = visitor.pass.result;
    971969
    972970                // handling for opaque type declarations (?)
  • src/ResolvExpr/ConversionCost.cc

    rfb0ae06 rdab09ad  
    481481        }
    482482
    483 namespace {
    484         # warning For overload resolution between the two versions.
    485         int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
    486                         const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
    487                 return ptrsAssignable( t1, t2, env );
    488         }
    489         Cost localConversionCost(
    490                 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
    491                 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
    492         ) { return conversionCost( src, dst, srcIsLvalue, symtab, env ); }
    493 }
     483static int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
     484                const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
     485        return ptrsAssignable( t1, t2, env );
     486}
     487
     488// TODO: This is used for overload resolution. It might be able to be dropped once the old system
     489// is removed.
     490static Cost localConversionCost(
     491        const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
     492        const ast::TypeEnvironment & env
     493) { return conversionCost( src, dst, symtab, env ); }
    494494
    495495Cost conversionCost(
    496         const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
    497         const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
     496        const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
     497        const ast::TypeEnvironment & env
    498498) {
    499499        if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
    500500                if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) {
    501501                        if ( eqv->bound ) {
    502                                 return conversionCost(src, eqv->bound, srcIsLvalue, symtab, env );
     502                                return conversionCost(src, eqv->bound, symtab, env );
    503503                        } else {
    504504                                return Cost::infinity;
     
    508508                        assertf( type, "Unexpected typedef." );
    509509                        if ( type->base ) {
    510                                 return conversionCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe;
     510                                return conversionCost( src, type->base, symtab, env ) + Cost::safe;
    511511                        }
    512512                }
     
    518518        } else if ( const ast::ReferenceType * refType =
    519519                         dynamic_cast< const ast::ReferenceType * >( dst ) ) {
    520                 return convertToReferenceCost( src, refType, srcIsLvalue, symtab, env, localPtrsAssignable );
     520                return convertToReferenceCost( src, refType, symtab, env, localPtrsAssignable );
    521521        } else {
    522                 ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
     522                ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
    523523                src->accept( converter );
    524                 return converter.core.cost;
    525         }
    526 }
    527 
    528 static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
     524                return converter.pass.cost;
     525        }
     526}
     527
     528static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst,
    529529                int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
    530                 PtrsCalculation func ) {
     530                NumCostCalculation func ) {
    531531        if ( 0 < diff ) {
    532532                Cost cost = convertToReferenceCost(
    533                         strict_dynamic_cast< const ast::ReferenceType * >( src )->base, dst,
    534                         srcIsLvalue, (diff - 1), symtab, env, func );
     533                        strict_dynamic_cast< const ast::ReferenceType * >( src )->base,
     534                        dst, (diff - 1), symtab, env, func );
    535535                cost.incReference();
    536536                return cost;
     
    538538                Cost cost = convertToReferenceCost(
    539539                        src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base,
    540                         srcIsLvalue, (diff + 1), symtab, env, func );
     540                        (diff + 1), symtab, env, func );
    541541                cost.incReference();
    542542                return cost;
     
    563563                        }
    564564                } else {
    565                         ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
     565                        ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
    566566                        src->accept( converter );
    567                         return converter.core.cost;
     567                        return converter.pass.cost;
    568568                }
    569569        } else {
     
    572572                assert( dstAsRef );
    573573                if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
    574                         if ( srcIsLvalue ) {
     574                        if ( src->is_lvalue() ) {
    575575                                if ( src->qualifiers == dstAsRef->base->qualifiers ) {
    576576                                        return Cost::reference;
     
    591591
    592592Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst,
    593                 bool srcIsLvalue, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
    594                 PtrsCalculation func ) {
     593            const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
     594                NumCostCalculation func ) {
    595595        int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth();
    596         return convertToReferenceCost( src, dst, srcIsLvalue, sdepth - ddepth, symtab, env, func );
     596        return convertToReferenceCost( src, dst, sdepth - ddepth, symtab, env, func );
    597597}
    598598
     
    651651        assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
    652652
    653         cost = costCalc( refType->base, dst, srcIsLvalue, symtab, env );
     653        cost = costCalc( refType->base, dst, symtab, env );
    654654        if ( refType->base->qualifiers == dst->qualifiers ) {
    655655                cost.incReference();
     
    667667void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
    668668        (void)enumInstType;
    669         static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
    670         cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
     669        static const ast::BasicType integer( ast::BasicType::SignedInt );
     670        cost = costCalc( &integer, dst, symtab, env );
    671671        if ( cost < Cost::unsafe ) {
    672672                cost.incSafe();
     
    680680void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) {
    681681        if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) {
    682                 cost = costCalc( eqv->bound, dst, srcIsLvalue, symtab, env );
     682                cost = costCalc( eqv->bound, dst, symtab, env );
    683683        } else if ( const ast::TypeInstType * dstAsInst =
    684684                        dynamic_cast< const ast::TypeInstType * >( dst ) ) {
     
    690690                assertf( type, "Unexpected typedef.");
    691691                if ( type->base ) {
    692                         cost = costCalc( type->base, dst, srcIsLvalue, symtab, env ) + Cost::safe;
     692                        cost = costCalc( type->base, dst, symtab, env ) + Cost::safe;
    693693                }
    694694        }
     
    703703                auto dstEnd = dstAsTuple->types.end();
    704704                while ( srcIt != srcEnd && dstIt != dstEnd ) {
    705                         Cost newCost = costCalc( * srcIt++, * dstIt++, srcIsLvalue, symtab, env );
     705                        Cost newCost = costCalc( * srcIt++, * dstIt++, symtab, env );
    706706                        if ( newCost == Cost::infinity ) {
    707707                                return;
     
    738738                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    739739                }
    740         } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
    741                 cost = Cost::zero;
    742                 // +1 for zero_t ->, +1 for disambiguation
    743                 cost.incSafe( maxIntCost + 2 );
    744740        }
    745741}
     
    759755                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    760756                }
    761         }
    762 }
    763 // size_t ConversionCost_new::traceId = Stats::Heap::new_stacktrace_id("ConversionCost");
     757        } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
     758                cost = Cost::zero;
     759                cost.incSafe( maxIntCost + 2 );
     760        }
     761}
     762
    764763
    765764} // namespace ResolvExpr
  • src/ResolvExpr/ConversionCost.h

    rfb0ae06 rdab09ad  
    7272
    7373// Some function pointer types, differ in return type.
    74 using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *, bool,
     74using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *,
    7575        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
    76 using PtrsCalculation = std::function<int(const ast::Type *, const ast::Type *,
     76using NumCostCalculation = std::function<int(const ast::Type *, const ast::Type *,
    7777        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
    7878
     
    8181protected:
    8282        const ast::Type * dst;
    83         bool srcIsLvalue;
    8483        const ast::SymbolTable & symtab;
    8584        const ast::TypeEnvironment & env;
    8685        CostCalculation costCalc;
    8786public:
    88         static size_t traceId;
    8987        Cost cost;
    9088
    91         ConversionCost_new( const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab,
     89        ConversionCost_new( const ast::Type * dst, const ast::SymbolTable & symtab,
    9290                        const ast::TypeEnvironment & env, CostCalculation costCalc ) :
    93                 dst( dst ), srcIsLvalue( srcIsLvalue ), symtab( symtab ), env( env ),
    94                 costCalc( costCalc ), cost( Cost::infinity )
     91                dst( dst ), symtab( symtab ), env( env ), costCalc( costCalc ), cost( Cost::infinity )
    9592        {}
    9693
     
    113110
    114111Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,
    115         bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env,
    116         PtrsCalculation func );
     112        const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, NumCostCalculation func );
    117113
    118114} // namespace ResolvExpr
  • src/ResolvExpr/CurrentObject.cc

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    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 ) {
     
    8786        ast::Pass<PolyCost_new> costing( symtab, env );
    8887        type->accept( costing );
    89         return costing.core.result;
     88        return costing.pass.result;
    9089}
    9190
  • src/ResolvExpr/PtrsAssignable.cc

    rfb0ae06 rdab09ad  
    155155                ast::Pass<PtrsAssignable_new> visitor( dst, env );
    156156                src->accept( visitor );
    157                 return visitor.core.result;
     157                return visitor.pass.result;
    158158        }
    159159
  • src/ResolvExpr/PtrsCastable.cc

    rfb0ae06 rdab09ad  
    293293                ast::Pass< PtrsCastable_new > ptrs{ dst, env, symtab };
    294294                src->accept( ptrs );
    295                 return ptrs.core.result;
     295                return ptrs.pass.result;
    296296        }
    297297}
  • src/ResolvExpr/RenameVars.cc

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    982982                ast::Pass<DeleteFinder_new> finder;
    983983                expr->accept( finder );
    984                 return finder.core.delExpr;
     984                return finder.pass.delExpr;
    985985        }
    986986
     
    10721072                /// Strips extraneous casts out of an expression
    10731073                struct StripCasts_new final {
    1074                         const ast::Expr * postvisit( const ast::CastExpr * castExpr ) {
     1074                        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() );
     
    12361236
    12371237        public:
    1238                 static size_t traceId;
    12391238                Resolver_new() = default;
    12401239                Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
     
    12671266                const ast::ConstructorInit * previsit( const ast::ConstructorInit * );
    12681267        };
    1269         // size_t Resolver_new::traceId = Stats::Heap::new_stacktrace_id("Resolver");
    1270 
    1271         void resolve( std::list< ast::ptr< ast::Decl > >& translationUnit ) {
    1272                 ast::Pass< Resolver_new >::run( translationUnit );
     1268
     1269        void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) {
     1270                ast::Pass< Resolver_new > resolver;
     1271                accept_all( translationUnit, resolver );
    12731272        }
    12741273
     
    13001299                // default value expressions have an environment which shouldn't be there and trips up
    13011300                // later passes.
    1302                 assert( functionDecl->unique() );
    1303                 ast::FunctionType * mutType = mutate( functionDecl->type.get() );
    1304 
    1305                 for ( unsigned i = 0 ; i < mutType->params.size() ; ++i ) {
    1306                         if ( const ast::ObjectDecl * obj = mutType->params[i].as< ast::ObjectDecl >() ) {
     1301                ast::ptr< ast::FunctionDecl > ret = functionDecl;
     1302                for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {
     1303                        const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i];
     1304
     1305                        if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {
    13071306                                if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) {
    13081307                                        if ( init->value->env == nullptr ) continue;
    13091308                                        // clone initializer minus the initializer environment
    1310                                         auto mutParam = mutate( mutType->params[i].strict_as< ast::ObjectDecl >() );
    1311                                         auto mutInit = mutate( mutParam->init.strict_as< ast::SingleInit >() );
    1312                                         auto mutValue = mutate( mutInit->value.get() );
    1313 
    1314                                         mutValue->env = nullptr;
    1315                                         mutInit->value = mutValue;
    1316                                         mutParam->init = mutInit;
    1317                                         mutType->params[i] = mutParam;
    1318 
    1319                                         assert( ! mutType->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env);
     1309                                        ast::chain_mutate( ret )
     1310                                                ( &ast::FunctionDecl::type )
     1311                                                        ( &ast::FunctionType::params )[i]
     1312                                                                ( &ast::ObjectDecl::init )
     1313                                                                        ( &ast::SingleInit::value )->env = nullptr;
     1314
     1315                                        assert( functionDecl != ret.get() || functionDecl->unique() );
     1316                                        assert( ! ret->type->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env );
    13201317                                }
    13211318                        }
    13221319                }
    1323                 mutate_field(functionDecl, &ast::FunctionDecl::type, mutType);
    1324                 return functionDecl;
     1320                return ret.get();
    13251321        }
    13261322
     
    13451341                // in case we decide to allow nested enums
    13461342                GuardValue( inEnumDecl );
    1347                 inEnumDecl = true;
     1343                inEnumDecl = false;
    13481344        }
    13491345
  • src/ResolvExpr/SatisfyAssertions.cpp

    rfb0ae06 rdab09ad  
    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
     
    188188
    189189                                matches.emplace_back(
    190                                         cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
     190                                        cdata, adjType, std::move( newEnv ), std::move( newNeed ), std::move( have ),
    191191                                        std::move( newOpen ), crntResnSlot );
    192192                        }
     
    229229                InferMatcher( InferCache & inferred ) : inferred( inferred ) {}
    230230
    231                 const ast::Expr * postvisit( const ast::Expr * expr ) {
     231                const ast::Expr * postmutate( const ast::Expr * expr ) {
    232232                        // Skip if no slots to find
    233                         if ( !expr->inferred.hasSlots() ) return expr;
    234                         // if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr;
    235                         std::vector<UniqueId> missingSlots;
     233                        if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr;
     234
    236235                        // find inferred parameters for resolution slots
    237                         ast::InferredParams * newInferred = new ast::InferredParams();
     236                        ast::InferredParams newInferred;
    238237                        for ( UniqueId slot : expr->inferred.resnSlots() ) {
    239238                                // fail if no matching assertions found
    240239                                auto it = inferred.find( slot );
    241240                                if ( it == inferred.end() ) {
    242                                         std::cerr << "missing assertion " << slot << std::endl;
    243                                         missingSlots.push_back(slot);
    244                                         continue;
     241                                        assert(!"missing assertion");
    245242                                }
    246243
     
    248245                                for ( auto & entry : it->second ) {
    249246                                        // recurse on inferParams of resolved expressions
    250                                         entry.second.expr = postvisit( entry.second.expr );
    251                                         auto res = newInferred->emplace( entry );
     247                                        entry.second.expr = postmutate( entry.second.expr );
     248                                        auto res = newInferred.emplace( entry );
    252249                                        assert( res.second && "all assertions newly placed" );
    253250                                }
     
    255252
    256253                        ast::Expr * ret = mutate( expr );
    257                         ret->inferred.set_inferParams( newInferred );
    258                         if (!missingSlots.empty()) ret->inferred.resnSlots() = missingSlots;
     254                        ret->inferred.set_inferParams( std::move( newInferred ) );
    259255                        return ret;
    260256                }
     
    303299                        Cost cost;
    304300
    305                         OutType(
    306                                 const ast::TypeEnvironment & e, const ast::OpenVarSet & o,
     301                        OutType( 
     302                                const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 
    307303                                const std::vector< DeferRef > & as, const ast::SymbolTable & symtab )
    308304                        : env( e ), open( o ), assns( as ), cost( Cost::zero ) {
     
    310306                                for ( const DeferRef & assn : assns ) {
    311307                                        // compute conversion cost from satisfying decl to assertion
    312                                         cost += computeConversionCost(
    313                                                 assn.match.adjType, assn.decl->get_type(), false, symtab, env );
    314 
     308                                        cost += computeConversionCost( 
     309                                                assn.match.adjType, assn.decl->get_type(), symtab, env );
     310                                       
    315311                                        // mark vars+specialization on function-type assertions
    316                                         const ast::FunctionType * func =
     312                                        const ast::FunctionType * func = 
    317313                                                GenPoly::getFunctionType( assn.match.cdata.id->get_type() );
    318314                                        if ( ! func ) continue;
     
    321317                                                cost.decSpec( specCost( param->get_type() ) );
    322318                                        }
    323 
     319                                       
    324320                                        cost.incVar( func->forall.size() );
    325 
     321                                       
    326322                                        for ( const ast::TypeDecl * td : func->forall ) {
    327323                                                cost.decSpec( td->assertions.size() );
     
    333329                };
    334330
    335                 CandidateEnvMerger(
    336                         const ast::TypeEnvironment & env, const ast::OpenVarSet & open,
     331                CandidateEnvMerger( 
     332                        const ast::TypeEnvironment & env, const ast::OpenVarSet & open, 
    337333                        const ast::SymbolTable & syms )
    338334                : crnt(), envs{ env }, opens{ open }, symtab( syms ) {}
  • src/ResolvExpr/SatisfyAssertions.hpp

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    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                        }
     
    217208        }
    218209        ast::Pass<SpecCounter> counter;
    219         type->accept( counter );
    220         return counter.core.get_count();
     210        type->accept( *counter.pass.visitor );
     211        return counter.pass.get_count();
    221212}
    222213
  • src/ResolvExpr/Unify.cc

    rfb0ae06 rdab09ad  
    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);
    171 
    172                 ast::ptr< ast::Type > subFirst = env.apply(newFirst).node;
    173                 ast::ptr< ast::Type > subSecond = env.apply(newSecond).node;
     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 );
    174177
    175178                return unifyExact(
    176                         subFirst,
    177                         subSecond,
    178                         newEnv, need, have, open, noWiden(), symtab );
     179                        newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
    179180        }
    180181
     
    325326
    326327        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;
    327333                AssertionSet::iterator i = assertions.find( assert );
    328334                if ( i != assertions.end() ) {
     335///     std::cerr << "found it!" << std::endl;
    329336                        i->second.isUsed = true;
    330337                } // if
     
    702709                const ast::SymbolTable & symtab;
    703710        public:
    704                 static size_t traceId;
    705711                bool result;
    706712
     
    937943
    938944        private:
    939                 // Returns: other, cast as XInstType
    940                 // Assigns this->result: whether types are compatible (up to generic parameters)
    941                 template< typename XInstType >
    942                 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 ) {
    943947                        // check that the other type is compatible and named the same
    944                         auto otherInst = dynamic_cast< const XInstType * >( other );
    945                         this->result = otherInst && inst->name == otherInst->name;
     948                        auto otherInst = dynamic_cast< const RefType * >( other );
     949                        result = otherInst && inst->name == otherInst->name;
    946950                        return otherInst;
    947951                }
     
    964968                }
    965969
    966                 template< typename XInstType >
    967                 void handleGenericRefType( const XInstType * inst, const ast::Type * other ) {
     970                template< typename RefType >
     971                void handleGenericRefType( const RefType * inst, const ast::Type * other ) {
    968972                        // check that other type is compatible and named the same
    969                         const XInstType * otherInst = handleRefType( inst, other );
    970                         if ( ! this->result ) return;
     973                        const RefType * inst2 = handleRefType( inst, other );
     974                        if ( ! inst2 ) return;
    971975
    972976                        // check that parameters of types unify, if any
    973977                        const std::vector< ast::ptr< ast::Expr > > & params = inst->params;
    974                         const std::vector< ast::ptr< ast::Expr > > & params2 = otherInst->params;
     978                        const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params;
    975979
    976980                        auto it = params.begin();
     
    11361140        };
    11371141
    1138         // size_t Unify_new::traceId = Stats::Heap::new_stacktrace_id("Unify_new");
    11391142        bool unify(
    11401143                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     
    11851188                        ast::Pass<Unify_new> comparator{ type2, env, need, have, open, widen, symtab };
    11861189                        type1->accept( comparator );
    1187                         return comparator.core.result;
     1190                        return comparator.pass.result;
    11881191                }
    11891192        }
     
    11991202                // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and
    12001203                // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1
    1201                 ast::Type * t1 = shallowCopy(type1.get());
    1202                 ast::Type * t2 = shallowCopy(type2.get());
    1203                 t1->qualifiers = {};
    1204                 t2->qualifiers = {};
    1205                 ast::ptr< ast::Type > t1_(t1);
    1206                 ast::ptr< ast::Type > t2_(t2);
     1204                ast::ptr<ast::Type> t1{ type1 }, t2{ type2 };
     1205                reset_qualifiers( t1 );
     1206                reset_qualifiers( t2 );
    12071207
    12081208                if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
     1209                        t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
     1210
    12091211                        // if exact unification on unqualified types, try to merge qualifiers
    12101212                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
    1211                                 t1->qualifiers = q1 | q2;
    1212                                 common = t1;
     1213                                common = type1;
     1214                                reset_qualifiers( common, q1 | q2 );
    12131215                                return true;
    12141216                        } else {
     
    12171219
    12181220                } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {
     1221                        t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
     1222
    12191223                        // no exact unification, but common type
    1220                         auto c = shallowCopy(common.get());
    1221                         c->qualifiers = q1 | q2;
    1222                         common = c;
     1224                        reset_qualifiers( common, q1 | q2 );
    12231225                        return true;
    12241226                } else {
  • src/ResolvExpr/typeops.h

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    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/SymTab/FixFunction.cc

    rfb0ae06 rdab09ad  
    106106                bool isVoid = false;
    107107
    108                 void previsit( const ast::FunctionDecl * ) { visit_children = false; }
     108                void premutate( const ast::FunctionDecl * ) { visit_children = false; }
    109109
    110                 const ast::DeclWithType * postvisit( const ast::FunctionDecl * func ) {
     110                const ast::DeclWithType * postmutate( const ast::FunctionDecl * func ) {
    111111                        return new ast::ObjectDecl{
    112112                                func->location, func->name, new ast::PointerType{ func->type }, nullptr,
     
    114114                }
    115115
    116                 void previsit( const ast::ArrayType * ) { visit_children = false; }
     116                void premutate( const ast::ArrayType * ) { visit_children = false; }
    117117
    118                 const ast::Type * postvisit( const ast::ArrayType * array ) {
     118                const ast::Type * postmutate( const ast::ArrayType * array ) {
    119119                        return new ast::PointerType{
    120120                                array->base, array->dimension, array->isVarLen, array->isStatic,
     
    122122                }
    123123
    124                 void previsit( const ast::VoidType * ) { isVoid = true; }
     124                void premutate( const ast::VoidType * ) { isVoid = true; }
    125125
    126                 void previsit( const ast::BasicType * ) { visit_children = false; }
    127                 void previsit( const ast::PointerType * ) { visit_children = false; }
    128                 void previsit( const ast::StructInstType * ) { visit_children = false; }
    129                 void previsit( const ast::UnionInstType * ) { visit_children = false; }
    130                 void previsit( const ast::EnumInstType * ) { visit_children = false; }
    131                 void previsit( const ast::TraitInstType * ) { visit_children = false; }
    132                 void previsit( const ast::TypeInstType * ) { visit_children = false; }
    133                 void previsit( const ast::TupleType * ) { visit_children = false; }
    134                 void previsit( const ast::VarArgsType * ) { visit_children = false; }
    135                 void previsit( const ast::ZeroType * ) { visit_children = false; }
    136                 void previsit( const ast::OneType * ) { visit_children = false; }
     126                void premutate( const ast::BasicType * ) { visit_children = false; }
     127                void premutate( const ast::PointerType * ) { visit_children = false; }
     128                void premutate( const ast::StructInstType * ) { visit_children = false; }
     129                void premutate( const ast::UnionInstType * ) { visit_children = false; }
     130                void premutate( const ast::EnumInstType * ) { visit_children = false; }
     131                void premutate( const ast::TraitInstType * ) { visit_children = false; }
     132                void premutate( const ast::TypeInstType * ) { visit_children = false; }
     133                void premutate( const ast::TupleType * ) { visit_children = false; }
     134                void premutate( const ast::VarArgsType * ) { visit_children = false; }
     135                void premutate( const ast::ZeroType * ) { visit_children = false; }
     136                void premutate( const ast::OneType * ) { visit_children = false; }
    137137        };
    138138} // anonymous namespace
     
    141141        ast::Pass< FixFunction_new > fixer;
    142142        dwt = dwt->accept( fixer );
    143         isVoid |= fixer.core.isVoid;
     143        isVoid |= fixer.pass.isVoid;
    144144        return dwt;
    145145}
  • src/SymTab/Mangler.cc

    rfb0ae06 rdab09ad  
    447447                ast::Pass<Mangler_new> mangler( mode );
    448448                maybeAccept( decl, mangler );
    449                 return mangler.core.get_mangleName();
     449                return mangler.pass.get_mangleName();
    450450        }
    451451
     
    691691                                                                mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
    692692                                                        assert->accept( sub_mangler );
    693                                                         assertionNames.push_back( sub_mangler.core.get_mangleName() );
     693                                                        assertionNames.push_back( sub_mangler.pass.get_mangleName() );
    694694                                                        acount++;
    695695                                                } // for
  • src/SynTree/ApplicationExpr.cc

    rfb0ae06 rdab09ad  
    3434
    3535ParamEntry::ParamEntry( const ParamEntry &other ) :
    36                 decl( other.decl ), declptr( other.declptr ), actualType( maybeClone( other.actualType ) ), formalType( maybeClone( other.formalType ) ), expr( maybeClone( other.expr ) ) {
     36                decl( other.decl ), declptr( maybeClone( other.declptr ) ), actualType( maybeClone( other.actualType ) ), formalType( maybeClone( other.formalType ) ), expr( maybeClone( other.expr ) ) {
    3737}
    3838
    3939ParamEntry::~ParamEntry() {
    40         // delete declptr;
     40        delete declptr;
    4141        delete actualType;
    4242        delete formalType;
  • src/SynTree/Statement.h

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    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 ) {
     
    147148        }
    148149
    149         const ast::Expr * postvisit( const ast::UniqueExpr * node ) {
     150        const ast::Expr * postmutate( const ast::UniqueExpr * node ) {
    150151                // move cast into unique expr so that the unique expr has type T& rather than
    151152                // type T. In particular, this transformation helps with generating the
     
    166167        }
    167168
    168         const ast::Expr * postvisit( const ast::TupleIndexExpr * tupleExpr ) {
     169        const ast::Expr * postmutate( const ast::TupleIndexExpr * tupleExpr ) {
    169170                // tuple index expr needs to be rebuilt to ensure that the type of the
    170171                // field is consistent with the type of the tuple expr, since the field
     
    179180        ast::Pass<CastExploderCore> exploder;
    180181        expr = expr->accept( exploder );
    181         if ( ! exploder.core.foundUniqueExpr ) {
     182        if ( ! exploder.pass.foundUniqueExpr ) {
    182183                expr = new ast::CastExpr{ expr, new ast::ReferenceType{ expr->result } };
    183184        }
  • src/Tuples/Explode.h

    rfb0ae06 rdab09ad  
    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

    rfb0ae06 rdab09ad  
    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 };
     
    504504
    505505                        std::vector< ast::ptr< ast::Expr > > match() override {
    506                                 // temporary workaround for new and old ast to coexist and avoid name collision
    507                                 static UniqueName lhsNamer( "__massassign_Ln" );
    508                                 static UniqueName rhsNamer( "__massassign_Rn" );
     506                                static UniqueName lhsNamer( "__massassign_L" );
     507                                static UniqueName rhsNamer( "__massassign_R" );
    509508                                // empty tuple case falls into this matcher
    510509                                assert( lhs.empty() ? rhs.empty() : rhs.size() <= 1 );
     
    535534
    536535                        std::vector< ast::ptr< ast::Expr > > match() override {
    537                                 // temporary workaround for new and old ast to coexist and avoid name collision
    538                                 static UniqueName lhsNamer( "__multassign_Ln" );
    539                                 static UniqueName rhsNamer( "__multassign_Rn" );
     536                                static UniqueName lhsNamer( "__multassign_L" );
     537                                static UniqueName rhsNamer( "__multassign_R" );
    540538
    541539                                if ( lhs.size() != rhs.size() ) return {};
     
    562560                                        // resolve the cast expression so that rhsCand return type is bound by the cast
    563561                                        // type as needed, and transfer the resulting environment
    564                                         ResolvExpr::CandidateFinder finder{ spotter.crntFinder.localSyms, env };
     562                                        ResolvExpr::CandidateFinder finder{ spotter.crntFinder.symtab, env };
    565563                                        finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() );
    566564                                        assert( finder.candidates.size() == 1 );
     
    611609                                        // explode the LHS so that each field of a tuple-valued expr is assigned
    612610                                        ResolvExpr::CandidateList lhs;
    613                                         explode( *lhsCand, crntFinder.localSyms, back_inserter(lhs), true );
     611                                        explode( *lhsCand, crntFinder.symtab, back_inserter(lhs), true );
    614612                                        for ( ResolvExpr::CandidateRef & cand : lhs ) {
    615613                                                // each LHS value must be a reference - some come in with a cast, if not
     
    631629                                                        if ( isTuple( rhsCand->expr ) ) {
    632630                                                                // multiple assignment
    633                                                                 explode( *rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
     631                                                                explode( *rhsCand, crntFinder.symtab, back_inserter(rhs), true );
    634632                                                                matcher.reset(
    635633                                                                        new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
     
    650648                                                        // multiple assignment
    651649                                                        ResolvExpr::CandidateList rhs;
    652                                                         explode( rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
     650                                                        explode( rhsCand, crntFinder.symtab, back_inserter(rhs), true );
    653651                                                        matcher.reset(
    654652                                                                new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
     
    680678                                )
    681679
    682                                 ResolvExpr::CandidateFinder finder{ crntFinder.localSyms, matcher->env };
     680                                ResolvExpr::CandidateFinder finder{ crntFinder.symtab, matcher->env };
    683681
    684682                                try {
  • src/Tuples/TupleExpansion.cc

    rfb0ae06 rdab09ad  
    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/Tuples/Tuples.cc

    rfb0ae06 rdab09ad  
    4343        };
    4444        struct ImpurityDetectorIgnoreUnique : public ImpurityDetector {
    45                 using ImpurityDetector::previsit;
    4645                void previsit( ast::UniqueExpr const * ) {
    4746                        visit_children = false;
     
    5352                ast::Pass<Detector> detector;
    5453                expr->accept( detector );
    55                 return detector.core.maybeImpure;
     54                return detector.pass.maybeImpure;
    5655        }
    5756} // namespace
  • src/config.h.in

    rfb0ae06 rdab09ad  
    2727/* Location of cfa install. */
    2828#undef CFA_PREFIX
    29 
    30 /* Sets whether or not to use the new-ast, this is adefault value and can be
    31    overrided by --old-ast and --new-ast */
    32 #undef CFA_USE_NEW_AST
    3329
    3430/* Major.Minor */
  • src/main.cc

    rfb0ae06 rdab09ad  
    3131using namespace std;
    3232
    33 #include "AST/Convert.hpp"
     33
    3434#include "CompilationState.h"
    3535#include "../config.h"                      // for CFA_LIBDIR
     
    340340                } // if
    341341
    342                 if( useNewAST) {
    343                         auto transUnit = convert( move( translationUnit ) );
    344                         PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
    345                         translationUnit = convert( move( transUnit ) );
    346                 } else {
    347                         PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
    348                 }
    349 
     342                PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
    350343                if ( exprp ) {
    351344                        dump( translationUnit );
     
    465458        { "prototypes", no_argument, nullptr, 'p' },
    466459        { "deterministic-out", no_argument, nullptr, 'd' },
    467         { "old-ast", no_argument, nullptr, 'O'},
    468         { "new-ast", no_argument, nullptr, 'A'},
    469460        { "print", required_argument, nullptr, 'P' },
    470461        { "prelude-dir", required_argument, nullptr, PreludeDir },
     
    488479        "generate prototypes for prelude functions",            // -p
    489480        "don't print output that isn't deterministic",        // -d
    490         "Use the old-ast",                                    // -O
    491         "Use the new-ast",                                    // -A
    492481        "print",                                              // -P
    493482        "<directory> prelude directory for debug/nodebug",      // no flag
     
    595584                        break;
    596585                  case 'd':                                     // don't print non-deterministic output
    597                         deterministic_output = true;
    598                         break;
    599                   case 'O':                                     // don't print non-deterministic output
    600                         useNewAST = false;
    601                         break;
    602                   case 'A':                                     // don't print non-deterministic output
    603                         useNewAST = true;
     586                    deterministic_output = true;
    604587                        break;
    605588                  case 'P':                                                                             // print options
Note: See TracChangeset for help on using the changeset viewer.