Changeset 4c925cd


Ignore:
Timestamp:
Aug 14, 2020, 11:40:04 AM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
5715d43, fa5e0112
Parents:
309d814 (diff), badd22f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
8 added
76 edited

Legend:

Unmodified
Added
Removed
  • configure.ac

    r309d814 r4c925cd  
    2424#Trasforming cc1 will break compilation
    2525M4CFA_PROGRAM_NAME
     26
     27#==============================================================================
     28# New AST toggling support
     29AH_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])
     30AC_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])
     37AC_DEFINE_UNQUOTED([CFA_USE_NEW_AST], $newast)
    2638
    2739#==============================================================================
  • driver/cc1.cc

    r309d814 r4c925cd  
    1010// Created On       : Fri Aug 26 14:23:51 2005
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat May 30 18:09:05 2020
    13 // Update Count     : 404
     12// Last Modified On : Thu Aug 13 21:03:15 2020
     13// Update Count     : 407
    1414//
    1515
     
    170170                        if ( arg == "-quiet" ) {
    171171                        } else if ( arg == "-imultilib" || arg == "-imultiarch" ) {
    172                                 i += 1;                                                                 // and the argument
     172                                i += 1;                                                                 // and argument
    173173                        } else if ( prefix( arg, "-A" ) ) {
    174174                        } else if ( prefix( arg, "-D__GNU" ) ) {
     
    177177                                //********
    178178                        } else if ( arg == "-D" && prefix( argv[i + 1], "__GNU" ) ) {
    179                                 i += 1;                                                                 // and the argument
     179                                i += 1;                                                                 // and argument
    180180
    181181                                // strip flags controlling cpp step
     
    184184                                cpp_flag = true;
    185185                        } else if ( arg == "-D" && string( argv[i + 1] ) == "__CPP__" ) {
    186                                 i += 1;                                                                 // and the argument
     186                                i += 1;                                                                 // and argument
    187187                                cpp_flag = true;
    188188
     
    194194                                cpp_out = argv[i];
    195195                        } else {
    196                                 args[nargs++] = argv[i];                                // pass the flag along
     196                                args[nargs++] = argv[i];                                // pass flag along
    197197                                // CPP flags with an argument
    198198                                if ( arg == "-D" || arg == "-U" || arg == "-I" || arg == "-MF" || arg == "-MT" || arg == "-MQ" ||
     
    200200                                         arg == "-iwithprefix" || arg == "-iwithprefixbefore" || arg == "-isystem" || arg == "-isysroot" ) {
    201201                                        i += 1;
    202                                         args[nargs++] = argv[i];                        // pass the argument along
     202                                        args[nargs++] = argv[i];                        // pass argument along
    203203                                        #ifdef __DEBUG_H__
    204204                                        cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
    205205                                        #endif // __DEBUG_H__
    206206                                } else if ( arg == "-MD" || arg == "-MMD" ) {
     207                                        // gcc frontend generates the dependency file-name after the -MD/-MMD flag, but it is necessary to
     208                                        // prefix that file name with -MF.
    207209                                        args[nargs++] = "-MF";                          // insert before file
    208210                                        i += 1;
    209                                         args[nargs++] = argv[i];                        // pass the argument along
     211                                        args[nargs++] = argv[i];                        // pass argument along
    210212                                        #ifdef __DEBUG_H__
    211213                                        cerr << "argv[" << i << "]:\"" << argv[i] << "\"" << endl;
     
    279281        // Run the C preprocessor and save the output in the given file.
    280282
    281         if ( fork() == 0 ) {                                                             // child process ?
     283        if ( fork() == 0 ) {                                                            // child process ?
    282284                // -o xxx.ii cannot be used to write the output file from cpp because no output file is created if cpp detects
    283285                // an error (e.g., cannot find include file). Whereas, output is always generated, even when there is an error,
     
    388390
    389391                        } else {
    390                                 args[nargs++] = argv[i];                                // pass the flag along
     392                                args[nargs++] = argv[i];                                // pass flag along
    391393                                if ( arg == "-o" ) {
    392394                                        i += 1;
    393395                                        cpp_out = argv[i];
    394                                         args[nargs++] = argv[i];                        // pass the argument along
     396                                        args[nargs++] = argv[i];                        // pass argument along
    395397                                        #ifdef __DEBUG_H__
    396398                                        cerr << "arg:\"" << argv[i] << "\"" << endl;
  • driver/cfa.cc

    r309d814 r4c925cd  
    1010// Created On       : Tue Aug 20 13:44:49 2002
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat May 30 18:28:23 2020
    13 // Update Count     : 433
     12// Last Modified On : Thu Aug 13 17:22:02 2020
     13// Update Count     : 435
    1414//
    1515
     
    180180
    181181                        if ( arg == "-Xlinker" || arg == "-o" ) {
    182                                 args[nargs++] = argv[i];                                // pass argument along
     182                                args[nargs++] = argv[i];                                // pass flag along
    183183                                i += 1;
    184184                                if ( i == argc ) continue;                              // next argument available ?
    185185                                args[nargs++] = argv[i];                                // pass argument along
    186186                                if ( arg == "-o" ) o_file = i;                  // remember file
    187                         } else if ( strncmp(arg.c_str(), "-XCFA", 5) == 0 ) {                           // CFA pass through
    188                                 if(arg.size() == 5) {
     187                        } else if ( strncmp(arg.c_str(), "-XCFA", 5) == 0 ) { // CFA pass through
     188                                if ( arg.size() == 5 ) {
    189189                                        i += 1;
    190                                         if ( i == argc ) continue;                              // next argument available ?
     190                                        if ( i == argc ) continue;                      // next argument available ?
    191191                                        Putenv( argv, argv[i] );
    192 
    193                                         // CFA specific arguments
    194                                 }
    195                                 else if(arg[5] == ',') {
     192                                } else if ( arg[5] == ',' ) {                   // CFA specific arguments
    196193                                        Putenv( argv, argv[i] + 6 );
    197 
    198                                         // CFA specific arguments
    199                                 }
    200                                 else {
     194                                } else {                                                                // CFA specific arguments
    201195                                        args[nargs++] = argv[i];
    202                                 }
    203 
     196                                } // if
    204197                        } else if ( arg == "-CFA" ) {
    205198                                CFA_flag = true;                                                // strip the -CFA flag
     
    235228                        } else if ( arg == "-v" ) {
    236229                                verbose = true;                                                 // verbosity required
    237                                 args[nargs++] = argv[i];                                // pass argument along
     230                                args[nargs++] = argv[i];                                // pass flag along
    238231                        } else if ( arg == "-g" ) {
    239232                                debugging = true;                                               // symbolic debugging required
    240                                 args[nargs++] = argv[i];                                // pass argument along
     233                                args[nargs++] = argv[i];                                // pass flag along
    241234                        } else if ( arg == "-save-temps" ) {
    242                                 args[nargs++] = argv[i];                                // pass argument along
     235                                args[nargs++] = argv[i];                                // pass flag along
    243236                                Putenv( argv, arg );                                    // save cfa-cpp output
    244237                        } else if ( prefix( arg, "-x" ) ) {                     // file suffix ?
    245238                                string lang;
    246                                 args[nargs++] = argv[i];                                // pass argument along
     239                                args[nargs++] = argv[i];                                // pass flag along
    247240                                if ( arg.length() == 2 ) {                              // separate argument ?
    248241                                        i += 1;
     
    261254                        } else if ( prefix( arg, "-std=" ) || prefix( arg, "--std=" ) ) {
    262255                                std_flag = true;                                                // -std=XX provided
    263                                 args[nargs++] = argv[i];                                // pass argument along
     256                                args[nargs++] = argv[i];                                // pass flag along
    264257                        } else if ( arg == "-w" ) {
    265                                 args[nargs++] = argv[i];                                // pass argument along
     258                                args[nargs++] = argv[i];                                // pass flag along
    266259                                Putenv( argv, arg );
    267260                        } else if ( prefix( arg, "-W" ) ) {                     // check before next tests
    268261                                if ( arg == "-Werror" || arg == "-Wall" ) {
    269                                         args[nargs++] = argv[i];                        // pass argument along
     262                                        args[nargs++] = argv[i];                        // pass flag along
    270263                                        Putenv( argv, argv[i] );
    271264                                } else {
     
    281274                                bprefix = arg.substr(2);                                // strip the -B flag
    282275                        } else if ( arg == "-c" || arg == "-S" || arg == "-E" || arg == "-M" || arg == "-MM" ) {
    283                                 args[nargs++] = argv[i];                                // pass argument along
     276                                args[nargs++] = argv[i];                                // pass flag along
    284277                                if ( arg == "-E" || arg == "-M" || arg == "-MM" ) {
    285278                                        cpp_flag = true;                                        // cpp only
    286279                                } // if
    287280                                link = false;                           // no linkage required
     281                        } else if ( arg == "-D" || arg == "-U" || arg == "-I" || arg == "-MF" || arg == "-MT" || arg == "-MQ" ||
     282                                                arg == "-include" || arg == "-imacros" || arg == "-idirafter" || arg == "-iprefix" ||
     283                                                arg == "-iwithprefix" || arg == "-iwithprefixbefore" || arg == "-isystem" || arg == "-isysroot" ) {
     284                                args[nargs++] = argv[i];                                // pass flag along
     285                                i += 1;
     286                                args[nargs++] = argv[i];                                // pass argument along
    288287                        } else if ( arg[1] == 'l' ) {
    289288                                // if the user specifies a library, load it after user code
  • libcfa/src/Makefile.am

    r309d814 r4c925cd  
    4444
    4545headers = common.hfa fstream.hfa heap.hfa iostream.hfa iterator.hfa limits.hfa rational.hfa \
    46                 time.hfa stdlib.hfa memory.hfa parseargs.hfa \
     46                time.hfa stdlib.hfa parseargs.hfa \
    4747                containers/maybe.hfa containers/pair.hfa containers/result.hfa containers/vector.hfa
    4848
  • libcfa/src/concurrency/invoke.h

    r309d814 r4c925cd  
    2626#ifndef _INVOKE_H_
    2727#define _INVOKE_H_
     28
     29        struct __cfaehm_try_resume_node;
     30        struct __cfaehm_base_exception_t;
     31        struct exception_context_t {
     32                struct __cfaehm_try_resume_node * top_resume;
     33                struct __cfaehm_base_exception_t * current_exception;
     34        };
    2835
    2936        struct __stack_context_t {
     
    5158                // base of stack
    5259                void * base;
     60
     61                // Information for exception handling.
     62                struct exception_context_t exception_context;
    5363        };
    5464
     
    8494        };
    8595
    86         static inline struct __stack_t * __get_stack( struct $coroutine * cor ) { return (struct __stack_t*)(((uintptr_t)cor->stack.storage) & ((uintptr_t)-2)); }
     96        static inline struct __stack_t * __get_stack( struct $coroutine * cor ) {
     97                return (struct __stack_t*)(((uintptr_t)cor->stack.storage) & ((uintptr_t)-2));
     98        }
    8799
    88100        // struct which calls the monitor is accepting
  • libcfa/src/concurrency/kernel/startup.cfa

    r309d814 r4c925cd  
    516516        ( this.terminated ){ 0 };
    517517        ( this.runner ){};
    518         init( this, name, _cltr );
     518
     519        disable_interrupts();
     520                init( this, name, _cltr );
     521        enable_interrupts( __cfaabi_dbg_ctx );
    519522
    520523        __cfadbg_print_safe(runtime_core, "Kernel : Starting core %p\n", &this);
     
    540543        free( this.stack );
    541544
    542         deinit( this );
     545        disable_interrupts();
     546                deinit( this );
     547        enable_interrupts( __cfaabi_dbg_ctx );
    543548}
    544549
  • libcfa/src/concurrency/ready_queue.cfa

    r309d814 r4c925cd  
    150150//  queues or removing them.
    151151uint_fast32_t ready_mutate_lock( void ) with(*__scheduler_lock) {
     152        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     153
    152154        // Step 1 : lock global lock
    153155        // It is needed to avoid processors that register mid Critical-Section
     
    164166        }
    165167
     168        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    166169        return s;
    167170}
    168171
    169172void ready_mutate_unlock( uint_fast32_t last_s ) with(*__scheduler_lock) {
     173        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     174
    170175        // Step 1 : release local locks
    171176        // This must be done while the global lock is held to avoid
     
    182187        /*paranoid*/ assert(true == lock);
    183188        __atomic_store_n(&lock, (bool)false, __ATOMIC_RELEASE);
     189
     190        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    184191}
    185192
     
    419426        // Actually pop the list
    420427        struct $thread * thrd;
    421         bool emptied;
    422         [thrd, emptied] = pop(lane);
     428        thrd = pop(lane);
    423429
    424430        /* paranoid */ verify(thrd);
     
    457463                        if(head(lane)->link.next == thrd) {
    458464                                $thread * pthrd;
    459                                 bool emptied;
    460                                 [pthrd, emptied] = pop(lane);
     465                                pthrd = pop(lane);
    461466
    462467                                /* paranoid */ verify( pthrd == thrd );
     
    608613                        while(!is_empty(lanes.data[idx])) {
    609614                                struct $thread * thrd;
    610                                 __attribute__((unused)) bool _;
    611                                 [thrd, _] = pop(lanes.data[idx]);
     615                                thrd = pop(lanes.data[idx]);
    612616
    613617                                push(cltr, thrd);
  • libcfa/src/concurrency/ready_subqueue.hfa

    r309d814 r4c925cd  
    144144// returns popped
    145145// returns true of lane was empty before push, false otherwise
    146 [$thread *, bool] pop(__intrusive_lane_t & this) {
     146$thread * 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, prev] = 0p;
     164        node->link.next = 0p;
     165        node->link.prev = 0p;
    165166
    166167        // Update head time stamp
     
    180181                /* paranoid */ verify(tail(this)->link.prev == head(this));
    181182                /* paranoid */ verify(head(this)->link.next == tail(this));
    182                 return [node, true];
     183                return node;
    183184        }
    184185        else {
     
    187188                /* paranoid */ verify(head(this)->link.next != tail(this));
    188189                /* paranoid */ verify(this.before.link.ts != 0);
    189                 return [node, false];
     190                return node;
    190191        }
    191192}
  • libcfa/src/exception.c

    r309d814 r4c925cd  
    1010// Created On       : Mon Jun 26 15:13:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr May 21 12:18:00 2020
    13 // Update Count     : 20
     12// Last Modified On : Wed Aug 12 13:55:00 2020
     13// Update Count     : 21
    1414//
    1515
     
    2828#include <unwind.h>
    2929#include <bits/debug.hfa>
     30#include "concurrency/invoke.h"
    3031#include "stdhdr/assert.h"
    3132
     
    5960
    6061// Temperary global exception context. Does not work with concurency.
    61 struct exception_context_t {
    62         struct __cfaehm_try_resume_node * top_resume;
    63 
    64         exception_t * current_exception;
    65         int current_handler_index;
    66 } static shared_stack = {NULL, NULL, 0};
     62static struct exception_context_t shared_stack = {NULL, NULL};
    6763
    6864// Get the current exception context.
     
    122118
    123119// MEMORY MANAGEMENT =========================================================
     120
     121struct __cfaehm_node {
     122        struct _Unwind_Exception unwind_exception;
     123        struct __cfaehm_node * next;
     124        int handler_index;
     125};
     126
     127#define NODE_TO_EXCEPT(node) ((exception_t *)(1 + (node)))
     128#define EXCEPT_TO_NODE(except) ((struct __cfaehm_node *)(except) - 1)
     129#define UNWIND_TO_NODE(unwind) ((struct __cfaehm_node *)(unwind))
     130#define NULL_MAP(map, ptr) ((ptr) ? (map(ptr)) : NULL)
    124131
    125132// How to clean up an exception in various situations.
     
    137144}
    138145
    139 // We need a piece of storage to raise the exception, for now its a single
    140 // piece.
    141 static struct _Unwind_Exception this_exception_storage;
    142 
    143 struct __cfaehm_node {
    144         struct __cfaehm_node * next;
    145 };
    146 
    147 #define NODE_TO_EXCEPT(node) ((exception_t *)(1 + (node)))
    148 #define EXCEPT_TO_NODE(except) ((struct __cfaehm_node *)(except) - 1)
    149 
    150146// Creates a copy of the indicated exception and sets current_exception to it.
    151147static void __cfaehm_allocate_exception( exception_t * except ) {
     
    161157        }
    162158
     159        // Initialize the node:
     160        exception_t * except_store = NODE_TO_EXCEPT(store);
     161        store->unwind_exception.exception_class = __cfaehm_exception_class;
     162        store->unwind_exception.exception_cleanup = __cfaehm_exception_cleanup;
     163        store->handler_index = 0;
     164        except->virtual_table->copy( except_store, except );
     165
    163166        // Add the node to the list:
    164         store->next = EXCEPT_TO_NODE(context->current_exception);
    165         context->current_exception = NODE_TO_EXCEPT(store);
    166 
    167         // Copy the exception to storage.
    168         except->virtual_table->copy( context->current_exception, except );
    169 
    170         // Set up the exception storage.
    171         this_exception_storage.exception_class = __cfaehm_exception_class;
    172         this_exception_storage.exception_cleanup = __cfaehm_exception_cleanup;
     167        store->next = NULL_MAP(EXCEPT_TO_NODE, context->current_exception);
     168        context->current_exception = except_store;
    173169}
    174170
     
    185181        if ( context->current_exception == except ) {
    186182                node = to_free->next;
    187                 context->current_exception = (node) ? NODE_TO_EXCEPT(node) : 0;
     183                context->current_exception = NULL_MAP(NODE_TO_EXCEPT, node);
    188184        } else {
    189185                node = EXCEPT_TO_NODE(context->current_exception);
     
    213209        // Verify actions follow the rules we expect.
    214210        verify((actions & _UA_CLEANUP_PHASE) && (actions & _UA_FORCE_UNWIND));
    215         verify(!(actions & (_UA_SEARCH_PHASE | _UA_HANDER_FRAME)));
     211        verify(!(actions & (_UA_SEARCH_PHASE | _UA_HANDLER_FRAME)));
    216212
    217213        if ( actions & _UA_END_OF_STACK ) {
     
    222218}
    223219
     220static struct _Unwind_Exception cancel_exception_storage;
     221
    224222// Cancel the current stack, prefroming approprate clean-up and messaging.
    225223void __cfaehm_cancel_stack( exception_t * exception ) {
    226224        // TODO: Detect current stack and pick a particular stop-function.
    227225        _Unwind_Reason_Code ret;
    228         ret = _Unwind_ForcedUnwind( &this_exception_storage, _Stop_Fn, (void*)0x22 );
     226        ret = _Unwind_ForcedUnwind( &cancel_exception_storage, _Stop_Fn, (void*)0x22 );
    229227        printf("UNWIND ERROR %d after force unwind\n", ret);
    230228        abort();
     
    247245static void __cfaehm_begin_unwind(void(*defaultHandler)(exception_t *)) {
    248246        struct exception_context_t * context = this_exception_context();
    249         struct _Unwind_Exception * storage = &this_exception_storage;
    250247        if ( NULL == context->current_exception ) {
    251248                printf("UNWIND ERROR missing exception in begin unwind\n");
    252249                abort();
    253250        }
     251        struct _Unwind_Exception * storage =
     252                &EXCEPT_TO_NODE(context->current_exception)->unwind_exception;
    254253
    255254        // Call stdlibc to raise the exception
     
    419418                                _Unwind_Reason_Code ret = (0 == index)
    420419                                        ? _URC_CONTINUE_UNWIND : _URC_HANDLER_FOUND;
    421                                 context->current_handler_index = index;
     420                                UNWIND_TO_NODE(unwind_exception)->handler_index = index;
    422421
    423422                                // Based on the return value, check if we matched the exception
     
    425424                                        __cfadbg_print_safe(exception, " handler found\n");
    426425                                } else {
     426                                        // TODO: Continue the search if there is more in the table.
    427427                                        __cfadbg_print_safe(exception, " no handler\n");
    428428                                }
     
    516516        // Exception handler
    517517        // Note: Saving the exception context on the stack breaks termination exceptions.
    518         catch_block( this_exception_context()->current_handler_index,
     518        catch_block( EXCEPT_TO_NODE( this_exception_context()->current_exception )->handler_index,
    519519                     this_exception_context()->current_exception );
    520520}
  • libcfa/src/iostream.cfa

    r309d814 r4c925cd  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Aug 10 09:32:14 2020
    13 // Update Count     : 1126
     12// Last Modified On : Tue Aug 11 22:16:33 2020
     13// Update Count     : 1128
    1414//
    1515
     
    3737
    3838forall( dtype ostype | ostream( ostype ) ) {
    39         ostype & ?|?( ostype & os, zero_t ) {
    40                 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    41                 fmt( os, "%d", 0n );
    42                 return os;
    43         } // ?|?
    44         void ?|?( ostype & os, zero_t z ) {
    45                 (ostype &)(os | z); ends( os );
    46         } // ?|?
    47 
    48         ostype & ?|?( ostype & os, one_t ) {
    49                 if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    50                 fmt( os, "%d", 1n );
    51                 return os;
    52         } // ?|?
    53         void ?|?( ostype & os, one_t o ) {
    54                 (ostype &)(os | o); ends( os );
    55         } // ?|?
    56 
    5739        ostype & ?|?( ostype & os, bool b ) {
    5840                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
  • libcfa/src/iostream.hfa

    r309d814 r4c925cd  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 16 07:43:32 2020
    13 // Update Count     : 348
     12// Last Modified On : Tue Aug 11 22:16:14 2020
     13// Update Count     : 350
    1414//
    1515
     
    6767
    6868forall( dtype ostype | ostream( ostype ) ) {
    69         ostype & ?|?( ostype &, zero_t );
    70         void ?|?( ostype &, zero_t );
    71         ostype & ?|?( ostype &, one_t );
    72         void ?|?( ostype &, one_t );
    73 
    7469        ostype & ?|?( ostype &, bool );
    7570        void ?|?( ostype &, bool );
  • libcfa/src/stdlib.hfa

    r309d814 r4c925cd  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 30 16:14:58 2020
    13 // Update Count     : 490
     12// Last Modified On : Tue Aug 11 21:11:46 2020
     13// Update Count     : 495
    1414//
    1515
     
    136136        T * alloc_set( char fill ) {
    137137                return (T *)memset( (T *)alloc(), (int)fill, sizeof(T) ); // initialize with fill value
    138         } // alloc
    139 
    140         T * alloc_set( T fill ) {
     138        } // alloc_set
     139
     140        T * alloc_set( const T & fill ) {
    141141                return (T *)memcpy( (T *)alloc(), &fill, sizeof(T) ); // initialize with fill value
    142         } // alloc
     142        } // alloc_set
    143143
    144144        T * alloc_set( size_t dim, char fill ) {
    145145                return (T *)memset( (T *)alloc( dim ), (int)fill, dim * sizeof(T) ); // initialize with fill value
    146         } // alloc
    147 
    148         T * alloc_set( size_t dim, T fill ) {
     146        } // alloc_set
     147
     148        T * alloc_set( size_t dim, const T & fill ) {
    149149                T * r = (T *)alloc( dim );
    150150                for ( i; dim ) { memcpy( &r[i], &fill, sizeof(T) ); } // initialize with fill value
    151151                return r;
    152         } // alloc
     152        } // alloc_set
    153153
    154154        T * alloc_set( size_t dim, const T fill[] ) {
    155155                return (T *)memcpy( (T *)alloc( dim ), fill, dim * sizeof(T) ); // initialize with fill value
    156         } // alloc
     156        } // alloc_set
    157157
    158158        T * alloc_set( T ptr[], size_t dim, char fill ) {       // realloc array with fill
     
    166166        } // alloc_set
    167167
    168         T * alloc_set( T ptr[], size_t dim, T & fill ) {        // realloc array with fill
     168        T * alloc_set( T ptr[], size_t dim, const T & fill ) {  // realloc array with fill
    169169                size_t odim = malloc_size( ptr ) / sizeof(T);   // current dimension
    170170                size_t nsize = dim * sizeof(T);                                 // new allocation
     
    177177                } // if
    178178                return nptr;
    179         } // alloc_align_set
     179        } // alloc_set
    180180} // distribution
    181181
     
    204204        T * alloc_align_set( size_t align, char fill ) {
    205205                return (T *)memset( (T *)alloc_align( align ), (int)fill, sizeof(T) ); // initialize with fill value
    206         } // alloc_align
    207 
    208         T * alloc_align_set( size_t align, T fill ) {
     206        } // alloc_align_set
     207
     208        T * alloc_align_set( size_t align, const T & fill ) {
    209209                return (T *)memcpy( (T *)alloc_align( align ), &fill, sizeof(T) ); // initialize with fill value
    210         } // alloc_align
     210        } // alloc_align_set
    211211
    212212        T * alloc_align_set( size_t align, size_t dim, char fill ) {
    213213                return (T *)memset( (T *)alloc_align( align, dim ), (int)fill, dim * sizeof(T) ); // initialize with fill value
    214         } // alloc_align
    215 
    216         T * alloc_align_set( size_t align, size_t dim, T fill ) {
     214        } // alloc_align_set
     215
     216        T * alloc_align_set( size_t align, size_t dim, const T & fill ) {
    217217                T * r = (T *)alloc_align( align, dim );
    218218                for ( i; dim ) { memcpy( &r[i], &fill, sizeof(T) ); } // initialize with fill value
    219219                return r;
    220         } // alloc_align
     220        } // alloc_align_set
    221221
    222222        T * alloc_align_set( size_t align, size_t dim, const T fill[] ) {
    223223                return (T *)memcpy( (T *)alloc_align( align, dim ), fill, dim * sizeof(T) );
    224         } // alloc_align
     224        } // alloc_align_set
    225225
    226226        T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ) {
     
    234234        } // alloc_align_set
    235235
    236         T * alloc_align_set( T ptr[], size_t align, size_t dim, T & fill ) {
     236        T * alloc_align_set( T ptr[], size_t align, size_t dim, const T & fill ) {
    237237                size_t odim = malloc_size( ptr ) / sizeof(T);   // current dimension
    238238                size_t nsize = dim * sizeof(T);                                 // new allocation
  • src/AST/Attribute.hpp

    r309d814 r4c925cd  
    5151        template<typename node_t>
    5252        friend node_t * mutate(const node_t * node);
     53        template<typename node_t>
     54    friend node_t * shallowCopy(const node_t * node);
    5355};
    5456
  • src/AST/CVQualifiers.hpp

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

    r309d814 r4c925cd  
    2020
    2121#include "AST/Attribute.hpp"
     22#include "AST/Copy.hpp"
    2223#include "AST/Decl.hpp"
    2324#include "AST/Expr.hpp"
     
    587588                assert( tgtResnSlots.empty() );
    588589
    589                 if ( srcInferred.mode == ast::Expr::InferUnion::Params ) {
     590                if ( srcInferred.data.inferParams ) {
    590591                        const ast::InferredParams &srcParams = srcInferred.inferParams();
    591592                        for (auto & srcParam : srcParams) {
     
    593594                                        srcParam.second.decl,
    594595                                        get<Declaration>().accept1(srcParam.second.declptr),
    595                                         get<Type>().accept1(srcParam.second.actualType),
    596                                         get<Type>().accept1(srcParam.second.formalType),
    597                                         get<Expression>().accept1(srcParam.second.expr)
     596                                        get<Type>().accept1(srcParam.second.actualType)->clone(),
     597                                        get<Type>().accept1(srcParam.second.formalType)->clone(),
     598                                        get<Expression>().accept1(srcParam.second.expr)->clone()
    598599                                ));
    599600                                assert(res.second);
    600601                        }
    601                 } else if ( srcInferred.mode == ast::Expr::InferUnion::Slots  ) {
     602                }
     603                if ( srcInferred.data.resnSlots ) {
    602604                        const ast::ResnSlots &srcSlots = srcInferred.resnSlots();
    603605                        for (auto srcSlot : srcSlots) {
     
    620622
    621623                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                }
    622635                return visitBaseExpr_skipResultType(src, tgt);
    623636        }
     
    979992
    980993        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                }
    981999                auto rslt = new StmtExpr(
    982                         get<CompoundStmt>().accept1(node->stmts)
     1000                        get<CompoundStmt>().accept1(stmts)
    9831001                );
    9841002
     
    19862004
    19872005                assert( oldInferParams.empty() || oldResnSlots.empty() );
    1988                 assert( newInferred.mode == ast::Expr::InferUnion::Empty );
     2006                // assert( newInferred.mode == ast::Expr::InferUnion::Empty );
    19892007
    19902008                if ( !oldInferParams.empty() ) {
     
    21172135                                old->location,
    21182136                                GET_ACCEPT_1(member, DeclWithType),
    2119                                 GET_ACCEPT_1(aggregate, Expr)
     2137                                GET_ACCEPT_1(aggregate, Expr),
     2138                                ast::MemberExpr::NoOpConstructionChosen
    21202139                        )
    21212140                );
  • src/AST/Decl.cpp

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

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

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

    r309d814 r4c925cd  
    3131
    3232// Must be included in *all* AST classes; should be #undef'd at the end of the file
    33 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     33#define MUTATE_FRIEND \
     34    template<typename node_t> friend node_t * mutate(const node_t * node); \
     35        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
     36
    3437
    3538class ConverterOldToNew;
     
    4245struct ParamEntry {
    4346        UniqueId decl;
    44         ptr<Decl> declptr;
     47        readonly<Decl> declptr;
    4548        ptr<Type> actualType;
    4649        ptr<Type> formalType;
     
    6265class Expr : public ParseNode {
    6366public:
    64         /// Saves space (~16 bytes) by combining ResnSlots and InferredParams
     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         */
    6573        struct InferUnion {
     74                // mode is now unused
    6675                enum { Empty, Slots, Params } mode;
    67                 union data_t {
    68                         char def;
    69                         ResnSlots resnSlots;
    70                         InferredParams inferParams;
    71 
    72                         data_t() : def('\0') {}
    73                         ~data_t() {}
     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                        }
    7487                } data;
    7588
    7689                /// initializes from other InferUnion
    7790                void init_from( const InferUnion& o ) {
    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;
     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);
    8296                        }
    8397                }
     
    8599                /// initializes from other InferUnion (move semantics)
    86100                void init_from( InferUnion&& o ) {
    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                         }
     101                        data.resnSlots = o.data.resnSlots;
     102                        data.inferParams = o.data.inferParams;
     103                        o.data.resnSlots = nullptr;
     104                        o.data.inferParams = nullptr;
    102105                }
    103106
     
    107110                InferUnion& operator= ( const InferUnion& ) = delete;
    108111                InferUnion& operator= ( InferUnion&& ) = delete;
    109                 ~InferUnion() { reset(); }
     112
     113                bool hasSlots() const { return data.resnSlots; }
    110114
    111115                ResnSlots& 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();
     116                        if (!data.resnSlots) {
     117                                data.resnSlots = new ResnSlots();
    116118                        }
    117                         assertf(false, "unreachable");
     119                        return *data.resnSlots;
    118120                }
    119121
    120122                const ResnSlots& resnSlots() const {
    121                         if (mode == Slots) {
    122                                 return data.resnSlots;
     123                        if (data.resnSlots) {
     124                                return *data.resnSlots;
    123125                        }
    124126                        assertf(false, "Mode was not already resnSlots");
     
    127129
    128130                InferredParams& inferParams() {
    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;
     131                        if (!data.inferParams) {
     132                                data.inferParams = new InferredParams();
    133133                        }
    134                         assertf(false, "unreachable");
     134                        return *data.inferParams;
    135135                }
    136136
    137137                const InferredParams& inferParams() const {
    138                         if (mode == Params) {
    139                                 return data.inferParams;
     138                        if (data.inferParams) {
     139                                return *data.inferParams;
    140140                        }
    141141                        assertf(false, "Mode was not already Params");
     
    143143                }
    144144
    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                         }
     145                void set_inferParams( InferredParams * ps ) {
     146                        delete data.resnSlots;
     147                        data.resnSlots = nullptr;
     148                        delete data.inferParams;
     149                        data.inferParams = ps;
    158150                }
    159151
     
    161153                /// and the other is in `Params`.
    162154                void splice( InferUnion && o ) {
    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);
     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;
    173160                                }
    174                         } else assertf(false, "invalid mode");
     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                        }
    175179                }
    176180        };
     
    185189
    186190        Expr * set_extension( bool ex ) { extension = ex; return this; }
     191        virtual bool get_lvalue() const;
    187192
    188193        virtual const Expr * accept( Visitor & v ) const override = 0;
     
    201206        ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} );
    202207
     208        bool get_lvalue() const final;
     209
    203210        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    204211private:
     
    215222        UntypedExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} )
    216223        : Expr( loc ), func( f ), args( std::move(as) ) {}
     224
     225        bool get_lvalue() const final;
    217226
    218227        /// Creates a new dereference expression
     
    291300        CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {}
    292301
     302        bool get_lvalue() const final;
     303
    293304        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    294305private:
     
    338349        : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); }
    339350
     351        bool get_lvalue() const final;
     352
    340353        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    341354private:
     
    352365        MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg );
    353366
     367        bool get_lvalue() const final;
     368
    354369        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    355370private:
    356371        MemberExpr * clone() const override { return new MemberExpr{ *this }; }
    357372        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;
    358380};
    359381
     
    365387        VariableExpr( const CodeLocation & loc );
    366388        VariableExpr( const CodeLocation & loc, const DeclWithType * v );
     389
     390        bool get_lvalue() const final;
    367391
    368392        /// generates a function pointer for a given function
     
    532556
    533557        CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
    534         : Expr( loc ), arg1( a1 ), arg2( a2 ) {}
     558        : Expr( loc ), arg1( a1 ), arg2( a2 ) {
     559                this->result = a2->result;
     560        }
     561
     562        bool get_lvalue() const final;
    535563
    536564        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
     
    605633        CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i );
    606634
     635        bool get_lvalue() const final;
     636
    607637        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
    608638private:
     
    660690
    661691        TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i );
     692
     693        bool get_lvalue() const final;
    662694
    663695        const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Fwd.hpp

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

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

    r309d814 r4c925cd  
    2525
    2626// Must be included in *all* AST classes; should be #undef'd at the end of the file
    27 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     27#define MUTATE_FRIEND \
     28    template<typename node_t> friend node_t * mutate(const node_t * node); \
     29        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    2830
    2931namespace ast {
  • src/AST/Node.cpp

    r309d814 r4c925cd  
    99// Author           : Thierry Delisle
    1010// Created On       : Thu May 16 14:16:00 2019
    11 // Last Modified By :
    12 // Last Modified On :
    13 // Update Count     :
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Jun  5 10:21:00 2020
     13// Update Count     : 1
    1414//
    1515
     
    1717#include "Fwd.hpp"
    1818
     19#include <csignal>  // MEMORY DEBUG -- for raise
    1920#include <iostream>
    2021
     
    2930#include "Print.hpp"
    3031
    31 template< typename node_t, enum ast::Node::ref_type ref_t >
    32 void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) { node->increment(ref_t); }
    33 
    34 template< typename node_t, enum ast::Node::ref_type ref_t >
    35 void ast::ptr_base<node_t, ref_t>::_dec( const node_t * node ) { node->decrement(ref_t); }
    36 
    37 template< typename node_t, enum ast::Node::ref_type ref_t >
    38 void ast::ptr_base<node_t, ref_t>::_check() const { if(node) assert(node->was_ever_strong == false || node->strong_count > 0); }
     32/// MEMORY DEBUG -- allows breaking on ref-count changes of dynamically chosen object.
     33/// Process to use in GDB:
     34///   break ast::Node::_trap()
     35///   run
     36///   set variable MEM_TRAP_OBJ = <target>
     37///   disable <first breakpoint>
     38///   continue
     39void * MEM_TRAP_OBJ = nullptr;
     40
     41void _trap( const void * node ) {
     42        if ( node == MEM_TRAP_OBJ ) std::raise(SIGTRAP);
     43}
     44
     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
     58template< typename node_t, enum ast::Node::ref_type ref_t >
     59void ast::ptr_base<node_t, ref_t>::_strict_fail() const {
     60        strict_fail(node);
     61}
     62
     63template< typename node_t, enum ast::Node::ref_type ref_t >
     64void ast::ptr_base<node_t, ref_t>::_inc( const node_t * node ) {
     65        node->increment(ref_t);
     66        _trap( node );
     67}
     68
     69template< typename node_t, enum ast::Node::ref_type ref_t >
     70void 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
     75template< typename node_t, enum ast::Node::ref_type ref_t >
     76void ast::ptr_base<node_t, ref_t>::_check() const {
     77        // if(node) assert(node->was_ever_strong == false || node->strong_count > 0);
     78}
    3979
    4080template< typename node_t, enum ast::Node::ref_type ref_t >
  • src/AST/Node.hpp

    r309d814 r4c925cd  
    1010// Created On       : Wed May 8 10:27:04 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Jun  3 13:26:00 2019
    13 // Update Count     : 5
     12// Last Modified On : Fri Jun 5 9:47:00 2020
     13// Update Count     : 6
    1414//
    1515
     
    3838        Node& operator= (const Node&) = delete;
    3939        Node& operator= (Node&&) = delete;
    40         virtual ~Node() = default;
     40        virtual ~Node() {}
    4141
    4242        virtual const Node * accept( Visitor & v ) const = 0;
     
    5757        template<typename node_t>
    5858        friend node_t * mutate(const node_t * node);
     59        template<typename node_t>
     60        friend node_t * shallowCopy(const node_t * node);
    5961
    6062        mutable size_t strong_count = 0;
     
    6971        }
    7072
    71         void decrement(ast::Node::ref_type ref) const {
     73        void decrement(ast::Node::ref_type ref, bool do_delete = true) const {
    7274                switch (ref) {
    7375                        case ref_type::strong: strong_count--; break;
     
    7577                }
    7678
    77                 if(!strong_count && !weak_count) {
     79                if( do_delete && !strong_count && !weak_count) {
    7880                        delete this;
    7981                }
     
    9496        assertf(
    9597                node->weak_count == 0,
    96                 "Error: mutating node with weak references to it will invalided some references"
     98                "Error: mutating node with weak references to it will invalidate some references"
    9799        );
    98100        return node->clone();
     
    104106        // skip mutate if equivalent
    105107        if ( node->*field == val ) return node;
    106        
     108
    107109        // mutate and return
    108110        node_t * ret = mutate( node );
     
    123125        (ret->*field)[i] = std::forward< field_t >( val );
    124126        return ret;
     127}
     128
     129/// Mutate an entire indexed collection by cloning to accepted value
     130template<typename node_t, typename parent_t, typename coll_t>
     131const node_t * mutate_each( const node_t * node, coll_t parent_t::* field, Visitor & v ) {
     132        for ( unsigned i = 0; i < (node->*field).size(); ++i ) {
     133                node = mutate_field_index( node, field, i, (node->*field)[i]->accept( v ) );
     134        }
     135        return node;
    125136}
    126137
     
    219230        operator const node_t * () const { _check(); return node; }
    220231
     232        const node_t * release() {
     233                const node_t * ret = node;
     234                if ( node ) {
     235                        _dec(node, false);
     236                        node = nullptr;
     237                }
     238                return ret;
     239        }
     240
    221241        /// wrapper for convenient access to dynamic_cast
    222242        template<typename o_node_t>
    223243        const o_node_t * as() const { _check(); return dynamic_cast<const o_node_t *>(node); }
    224244
    225         /// wrapper for convenient access to strict_dynamic_cast
     245        /// Wrapper that makes sure dynamic_cast returns non-null.
    226246        template<typename o_node_t>
    227         const o_node_t * strict_as() const { _check(); return strict_dynamic_cast<const o_node_t *>(node); }
     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; }
    228255
    229256        /// Returns a mutable version of the pointer in this node.
     
    244271
    245272        void _inc( const node_t * other );
    246         void _dec( const node_t * other );
     273        void _dec( const node_t * other, bool do_delete = true );
    247274        void _check() const;
     275        void _strict_fail() const __attribute__((noreturn));
    248276
    249277        const node_t * node;
  • src/AST/Pass.hpp

    r309d814 r4c925cd  
    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
    3739// Private prelude header, needed for some of the magic tricks this class pulls off
    3840#include "AST/Pass.proto.hpp"
     
    4648//
    4749// Several additional features are available through inheritance
    48 // | WithTypeSubstitution - provides polymorphic const TypeSubstitution * env for the
    49 //                          current expression
    50 // | WithStmtsToAdd       - provides the ability to insert statements before or after the current
    51 //                          statement by adding new statements into stmtsToAddBefore or
    52 //                          stmtsToAddAfter respectively.
    53 // | WithDeclsToAdd       - provides the ability to insert declarations before or after the current
    54 //                          declarations by adding new DeclStmt into declsToAddBefore or
    55 //                          declsToAddAfter respectively.
    56 // | WithShortCircuiting  - provides the ability to skip visiting child nodes; set visit_children
    57 //                          to false in pre{visit,visit} to skip visiting children
    58 // | WithGuards           - provides the ability to save/restore data like a LIFO stack; to save,
    59 //                          call GuardValue with the variable to save, the variable will
    60 //                          automatically be restored to its previous value after the corresponding
    61 //                          postvisit/postmutate teminates.
    62 // | WithVisitorRef       - provides an pointer to the templated visitor wrapper
    63 // | WithSymbolTable      - provides symbol table functionality
     50// | WithTypeSubstitution  - provides polymorphic const TypeSubstitution * env for the
     51//                           current expression
     52// | WithStmtsToAdd        - provides the ability to insert statements before or after the current
     53//                           statement by adding new statements into stmtsToAddBefore or
     54//                           stmtsToAddAfter respectively.
     55// | WithDeclsToAdd        - provides the ability to insert declarations before or after the
     56//                           current declarations by adding new DeclStmt into declsToAddBefore or
     57//                           declsToAddAfter respectively.
     58// | WithShortCircuiting   - provides the ability to skip visiting child nodes; set visit_children
     59//                           to false in pre{visit,visit} to skip visiting children
     60// | WithGuards            - provides the ability to save/restore data like a LIFO stack; to save,
     61//                           call GuardValue with the variable to save, the variable will
     62//                           automatically be restored to its previous value after the
     63//                           corresponding postvisit/postmutate teminates.
     64// | WithVisitorRef        - provides an pointer to the templated visitor wrapper
     65// | WithSymbolTable       - provides symbol table functionality
     66// | WithForallSubstitutor - maintains links between TypeInstType and TypeDecl under mutation
    6467//-------------------------------------------------------------------------------------------------
    65 template< typename pass_t >
     68template< typename core_t >
    6669class Pass final : public ast::Visitor {
    6770public:
     71        using core_type = core_t;
     72        using type = Pass<core_t>;
     73
    6874        /// Forward any arguments to the pass constructor
    6975        /// Propagate 'this' if necessary
    7076        template< typename... Args >
    7177        Pass( Args &&... args)
    72                 : pass( std::forward<Args>( args )... )
     78                : core( std::forward<Args>( args )... )
    7379        {
    7480                // After the pass is constructed, check if it wants the have a pointer to the wrapping visitor
    75                 typedef Pass<pass_t> this_t;
    76                 this_t * const * visitor = __pass::visitor(pass, 0);
     81                type * const * visitor = __pass::visitor(core, 0);
    7782                if(visitor) {
    78                         *const_cast<this_t **>( visitor ) = this;
     83                        *const_cast<type **>( visitor ) = this;
    7984                }
    8085        }
     
    8287        virtual ~Pass() = default;
    8388
     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
     96        template< typename... Args >
     97        static void run( std::list< ptr<Decl> > & decls ) {
     98                Pass<core_t> visitor;
     99                accept_all( decls, visitor );
     100        }
     101
    84102        /// Storage for the actual pass
    85         pass_t pass;
     103        core_t core;
    86104
    87105        /// Visit function declarations
     
    179197        const ast::TypeSubstitution * visit( const ast::TypeSubstitution     * ) override final;
    180198
    181         template<typename pass_type>
    182         friend void accept_all( std::list< ptr<Decl> > & decls, Pass<pass_type>& visitor );
     199        template<typename core_type>
     200        friend void accept_all( std::list< ptr<Decl> > & decls, Pass<core_type>& visitor );
    183201private:
    184202
    185         bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children(pass, 0); return ptr ? *ptr : true; }
     203        bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children(core, 0); return ptr ? *ptr : true; }
    186204
    187205private:
     
    202220        container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
    203221
     222        /// Mutate forall-list, accounting for presence of type substitution map
     223        template<typename node_t>
     224        void mutate_forall( const node_t *& );
     225
    204226public:
    205227        /// Logic to call the accept and mutate the parent if needed, delegates call to accept
     
    210232        /// Internal RAII guard for symbol table features
    211233        struct guard_symtab {
    212                 guard_symtab( Pass<pass_t> & pass ): pass( pass ) { __pass::symtab::enter(pass, 0); }
    213                 ~guard_symtab()                                   { __pass::symtab::leave(pass, 0); }
    214                 Pass<pass_t> & pass;
     234                guard_symtab( Pass<core_t> & pass ): pass( pass ) { __pass::symtab::enter(pass.core, 0); }
     235                ~guard_symtab()                                   { __pass::symtab::leave(pass.core, 0); }
     236                Pass<core_t> & pass;
    215237        };
    216238
    217239        /// Internal RAII guard for scope features
    218240        struct guard_scope {
    219                 guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass, 0); }
    220                 ~guard_scope()                                   { __pass::scope::leave(pass, 0); }
    221                 Pass<pass_t> & pass;
     241                guard_scope( Pass<core_t> & pass ): pass( pass ) { __pass::scope::enter(pass.core, 0); }
     242                ~guard_scope()                                   { __pass::scope::leave(pass.core, 0); }
     243                Pass<core_t> & pass;
     244        };
     245
     246        /// Internal RAII guard for forall substitutions
     247        struct guard_forall_subs {
     248                guard_forall_subs( Pass<core_t> & pass, const ParameterizedType * type )
     249                : pass( pass ), type( type ) { __pass::forall::enter(pass.core, 0, type ); }
     250                ~guard_forall_subs()         { __pass::forall::leave(pass.core, 0, type ); }
     251                Pass<core_t> & pass;
     252                const ParameterizedType * type;
    222253        };
    223254
     
    227258
    228259/// Apply a pass to an entire translation unit
    229 template<typename pass_t>
    230 void accept_all( std::list< ast::ptr<ast::Decl> > &, ast::Pass<pass_t> & visitor );
     260template<typename core_t>
     261void accept_all( std::list< ast::ptr<ast::Decl> > &, ast::Pass<core_t> & visitor );
    231262
    232263//-------------------------------------------------------------------------------------------------
     
    268299        };
    269300
    270         template< typename pass_t>
    271         friend auto __pass::at_cleanup( pass_t & pass, int ) -> decltype( &pass.at_cleanup );
     301        template< typename core_t>
     302        friend auto __pass::at_cleanup( core_t & core, int ) -> decltype( &core.at_cleanup );
    272303public:
    273304
     
    305336
    306337/// Used to get a pointer to the pass with its wrapped type
    307 template<typename pass_t>
     338template<typename core_t>
    308339struct WithVisitorRef {
    309         Pass<pass_t> * const visitor = nullptr;
     340        Pass<core_t> * const visitor = nullptr;
    310341};
    311342
     
    314345        SymbolTable symtab;
    315346};
     347
     348/// Use when the templated visitor needs to keep TypeInstType instances properly linked to TypeDecl
     349struct WithForallSubstitutor {
     350        ForallSubstitutionTable subs;
     351};
     352
    316353}
    317354
     
    321358extern struct PassVisitorStats {
    322359        size_t depth = 0;
    323         Stats::Counters::MaxCounter<double> * max = nullptr;
    324         Stats::Counters::AverageCounter<double> * avg = nullptr;
     360        Stats::Counters::MaxCounter<double> * max;
     361        Stats::Counters::AverageCounter<double> * avg;
    325362} pass_visitor_stats;
    326363}
  • src/AST/Pass.impl.hpp

    r309d814 r4c925cd  
    2525        using namespace ast; \
    2626        /* back-up the visit children */ \
    27         __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(pass, 0) ); \
     27        __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(core, 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    (pass, 0) ); \
     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 ); \
    3032        /* call the implementation of the previsit of this pass */ \
    31         __pass::previsit( pass, node, 0 );
     33        __pass::previsit( core, node, 0 );
    3234
    3335#define VISIT( code... ) \
     
    4042#define VISIT_END( type, node ) \
    4143        /* call the implementation of the postvisit of this pass */ \
    42         auto __return = __pass::postvisit( pass, node, 0 ); \
     44        auto __return = __pass::postvisit( core, node, 0 ); \
    4345        assertf(__return, "post visit should never return null"); \
     46        /* end tracing memory allocation if requested by this pass */ \
     47        __pass::endTrace( core, 0 ); \
    4448        return __return;
    4549
     
    119123        }
    120124
    121         template< typename pass_t >
     125        template< typename core_t >
    122126        template< typename node_t >
    123         auto ast::Pass< pass_t >::call_accept( const node_t * node )
     127        auto ast::Pass< core_t >::call_accept( const node_t * node )
    124128                -> typename std::enable_if<
    125129                                !std::is_base_of<ast::Expr, node_t>::value &&
     
    127131                        , decltype( node->accept(*this) )
    128132                >::type
    129 
    130133        {
    131134                __pedantic_pass_assert( __visit_children() );
    132                 __pedantic_pass_assert( expr );
     135                __pedantic_pass_assert( node );
    133136
    134137                static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR");
     
    138141        }
    139142
    140         template< typename pass_t >
    141         const ast::Expr * ast::Pass< pass_t >::call_accept( const ast::Expr * expr ) {
     143        template< typename core_t >
     144        const ast::Expr * ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
    142145                __pedantic_pass_assert( __visit_children() );
    143146                __pedantic_pass_assert( expr );
    144147
    145                 const ast::TypeSubstitution ** env_ptr = __pass::env( pass, 0);
     148                const ast::TypeSubstitution ** env_ptr = __pass::env( core, 0);
    146149                if ( env_ptr && expr->env ) {
    147150                        *env_ptr = expr->env;
     
    151154        }
    152155
    153         template< typename pass_t >
    154         const ast::Stmt * ast::Pass< pass_t >::call_accept( const ast::Stmt * stmt ) {
     156        template< typename core_t >
     157        const ast::Stmt * ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
    155158                __pedantic_pass_assert( __visit_children() );
    156159                __pedantic_pass_assert( stmt );
     
    160163
    161164                // get the stmts/decls that will need to be spliced in
    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);
     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);
    166169
    167170                // These may be modified by subnode but most be restored once we exit this statemnet.
    168                 ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::env( pass, 0) );
     171                ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::env( core, 0) );
    169172                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
    170173                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
     
    202205        }
    203206
    204         template< typename pass_t >
     207        template< typename core_t >
    205208        template< template <class...> class container_t >
    206         container_t< ptr<Stmt> > ast::Pass< pass_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
     209        container_t< ptr<Stmt> > ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
    207210                __pedantic_pass_assert( __visit_children() );
    208211                if( statements.empty() ) return {};
     
    215218
    216219                // get the stmts/decls that will need to be spliced in
    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);
     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);
    221224
    222225                // These may be modified by subnode but most be restored once we exit this statemnet.
     
    268271        }
    269272
    270         template< typename pass_t >
     273        template< typename core_t >
    271274        template< template <class...> class container_t, typename node_t >
    272         container_t< ast::ptr<node_t> > ast::Pass< pass_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
     275        container_t< ast::ptr<node_t> > ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
    273276                __pedantic_pass_assert( __visit_children() );
    274277                if( container.empty() ) return {};
     
    299302        }
    300303
    301         template< typename pass_t >
     304        template< typename core_t >
    302305        template<typename node_t, typename parent_t, typename child_t>
    303         void ast::Pass< pass_t >::maybe_accept(
     306        void ast::Pass< core_t >::maybe_accept(
    304307                const node_t * & parent,
    305308                child_t parent_t::*child
     
    323326        }
    324327
     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        }
    325344}
    326345
     
    333352//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    334353
    335 template< typename pass_t >
    336 inline void ast::accept_all( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< pass_t > & visitor ) {
     354template< typename core_t >
     355inline void ast::accept_all( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< core_t > & visitor ) {
    337356        // We are going to aggregate errors for all these statements
    338357        SemanticErrorException errors;
     
    342361
    343362        // get the stmts/decls that will need to be spliced in
    344         auto decls_before = __pass::declsToAddBefore( visitor.pass, 0);
    345         auto decls_after  = __pass::declsToAddAfter ( visitor.pass, 0);
     363        auto decls_before = __pass::declsToAddBefore( visitor.core, 0);
     364        auto decls_after  = __pass::declsToAddAfter ( visitor.core, 0);
    346365
    347366        // update pass statitistics
     
    392411//--------------------------------------------------------------------------
    393412// ObjectDecl
    394 template< typename pass_t >
    395 const ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::ObjectDecl * node ) {
     413template< typename core_t >
     414const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::ObjectDecl * node ) {
    396415        VISIT_START( node );
    397416
     
    406425        )
    407426
    408         __pass::symtab::addId( pass, 0, node );
     427        __pass::symtab::addId( core, 0, node );
    409428
    410429        VISIT_END( DeclWithType, node );
     
    413432//--------------------------------------------------------------------------
    414433// FunctionDecl
    415 template< typename pass_t >
    416 const ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::FunctionDecl * node ) {
    417         VISIT_START( node );
    418 
    419         __pass::symtab::addId( pass, 0, node );
     434template< typename core_t >
     435const ast::DeclWithType * ast::Pass< core_t >::visit( const ast::FunctionDecl * node ) {
     436        VISIT_START( node );
     437
     438        __pass::symtab::addId( core, 0, node );
    420439
    421440        VISIT(maybe_accept( node, &FunctionDecl::withExprs );)
     
    425444                // shadow with exprs and not the other way around.
    426445                guard_symtab guard { *this };
    427                 __pass::symtab::addWith( pass, 0, node->withExprs, node );
     446                __pass::symtab::addWith( core, 0, node->withExprs, node );
    428447                {
    429448                        guard_symtab guard { *this };
    430449                        // implicit add __func__ identifier as specified in the C manual 6.4.2.2
    431                         static ast::ObjectDecl func(
    432                                 node->location, "__func__",
    433                                 new ast::ArrayType(
    434                                         new ast::BasicType( ast::BasicType::Char, ast::CV::Qualifiers( ast::CV::Const ) ),
     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 },
    435454                                        nullptr, VariableLen, DynamicDim
    436                                 )
    437                         );
    438                         __pass::symtab::addId( pass, 0, &func );
     455                                }
     456                        } };
     457                        __pass::symtab::addId( core, 0, func );
    439458                        VISIT(
    440459                                maybe_accept( node, &FunctionDecl::type );
     
    454473//--------------------------------------------------------------------------
    455474// StructDecl
    456 template< typename pass_t >
    457 const ast::Decl * ast::Pass< pass_t >::visit( const ast::StructDecl * node ) {
     475template< typename core_t >
     476const ast::Decl * ast::Pass< core_t >::visit( const ast::StructDecl * node ) {
    458477        VISIT_START( node );
    459478
    460479        // make up a forward declaration and add it before processing the members
    461480        // needs to be on the heap because addStruct saves the pointer
    462         __pass::symtab::addStructFwd( pass, 0, node );
     481        __pass::symtab::addStructFwd( core, 0, node );
    463482
    464483        VISIT({
     
    469488
    470489        // this addition replaces the forward declaration
    471         __pass::symtab::addStruct( pass, 0, node );
     490        __pass::symtab::addStruct( core, 0, node );
    472491
    473492        VISIT_END( Decl, node );
     
    476495//--------------------------------------------------------------------------
    477496// UnionDecl
    478 template< typename pass_t >
    479 const ast::Decl * ast::Pass< pass_t >::visit( const ast::UnionDecl * node ) {
     497template< typename core_t >
     498const ast::Decl * ast::Pass< core_t >::visit( const ast::UnionDecl * node ) {
    480499        VISIT_START( node );
    481500
    482501        // make up a forward declaration and add it before processing the members
    483         __pass::symtab::addUnionFwd( pass, 0, node );
     502        __pass::symtab::addUnionFwd( core, 0, node );
    484503
    485504        VISIT({
     
    489508        })
    490509
    491         __pass::symtab::addUnion( pass, 0, node );
     510        __pass::symtab::addUnion( core, 0, node );
    492511
    493512        VISIT_END( Decl, node );
     
    496515//--------------------------------------------------------------------------
    497516// EnumDecl
    498 template< typename pass_t >
    499 const ast::Decl * ast::Pass< pass_t >::visit( const ast::EnumDecl * node ) {
    500         VISIT_START( node );
    501 
    502         __pass::symtab::addEnum( pass, 0, node );
     517template< typename core_t >
     518const ast::Decl * ast::Pass< core_t >::visit( const ast::EnumDecl * node ) {
     519        VISIT_START( node );
     520
     521        __pass::symtab::addEnum( core, 0, node );
    503522
    504523        VISIT(
     
    513532//--------------------------------------------------------------------------
    514533// TraitDecl
    515 template< typename pass_t >
    516 const ast::Decl * ast::Pass< pass_t >::visit( const ast::TraitDecl * node ) {
     534template< typename core_t >
     535const ast::Decl * ast::Pass< core_t >::visit( const ast::TraitDecl * node ) {
    517536        VISIT_START( node );
    518537
     
    523542        })
    524543
    525         __pass::symtab::addTrait( pass, 0, node );
     544        __pass::symtab::addTrait( core, 0, node );
    526545
    527546        VISIT_END( Decl, node );
     
    530549//--------------------------------------------------------------------------
    531550// TypeDecl
    532 template< typename pass_t >
    533 const ast::Decl * ast::Pass< pass_t >::visit( const ast::TypeDecl * node ) {
     551template< typename core_t >
     552const ast::Decl * ast::Pass< core_t >::visit( const ast::TypeDecl * node ) {
    534553        VISIT_START( node );
    535554
     
    543562        // note that assertions come after the type is added to the symtab, since they are not part of the type proper
    544563        // and may depend on the type itself
    545         __pass::symtab::addType( pass, 0, node );
     564        __pass::symtab::addType( core, 0, node );
    546565
    547566        VISIT(
     
    559578//--------------------------------------------------------------------------
    560579// TypedefDecl
    561 template< typename pass_t >
    562 const ast::Decl * ast::Pass< pass_t >::visit( const ast::TypedefDecl * node ) {
     580template< typename core_t >
     581const ast::Decl * ast::Pass< core_t >::visit( const ast::TypedefDecl * node ) {
    563582        VISIT_START( node );
    564583
     
    569588        })
    570589
    571         __pass::symtab::addType( pass, 0, node );
     590        __pass::symtab::addType( core, 0, node );
    572591
    573592        VISIT( maybe_accept( node, &TypedefDecl::assertions ); )
     
    578597//--------------------------------------------------------------------------
    579598// AsmDecl
    580 template< typename pass_t >
    581 const ast::AsmDecl * ast::Pass< pass_t >::visit( const ast::AsmDecl * node ) {
     599template< typename core_t >
     600const ast::AsmDecl * ast::Pass< core_t >::visit( const ast::AsmDecl * node ) {
    582601        VISIT_START( node );
    583602
     
    591610//--------------------------------------------------------------------------
    592611// StaticAssertDecl
    593 template< typename pass_t >
    594 const ast::StaticAssertDecl * ast::Pass< pass_t >::visit( const ast::StaticAssertDecl * node ) {
     612template< typename core_t >
     613const ast::StaticAssertDecl * ast::Pass< core_t >::visit( const ast::StaticAssertDecl * node ) {
    595614        VISIT_START( node );
    596615
     
    605624//--------------------------------------------------------------------------
    606625// CompoundStmt
    607 template< typename pass_t >
    608 const ast::CompoundStmt * ast::Pass< pass_t >::visit( const ast::CompoundStmt * node ) {
     626template< typename core_t >
     627const ast::CompoundStmt * ast::Pass< core_t >::visit( const ast::CompoundStmt * node ) {
    609628        VISIT_START( node );
    610629        VISIT({
    611630                // do not enter a new scope if inFunction is true - needs to check old state before the assignment
    612                 auto guard1 = makeFuncGuard( [this, inFunction = this->inFunction]() {
    613                         if ( ! inFunction ) __pass::symtab::enter(pass, 0);
    614                 }, [this, inFunction = this->inFunction]() {
    615                         if ( ! inFunction ) __pass::symtab::leave(pass, 0);
     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);
    616635                });
    617636                ValueGuard< bool > guard2( inFunction );
     
    625644//--------------------------------------------------------------------------
    626645// ExprStmt
    627 template< typename pass_t >
    628 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ExprStmt * node ) {
     646template< typename core_t >
     647const ast::Stmt * ast::Pass< core_t >::visit( const ast::ExprStmt * node ) {
    629648        VISIT_START( node );
    630649
     
    638657//--------------------------------------------------------------------------
    639658// AsmStmt
    640 template< typename pass_t >
    641 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::AsmStmt * node ) {
     659template< typename core_t >
     660const ast::Stmt * ast::Pass< core_t >::visit( const ast::AsmStmt * node ) {
    642661        VISIT_START( node )
    643662
     
    654673//--------------------------------------------------------------------------
    655674// DirectiveStmt
    656 template< typename pass_t >
    657 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::DirectiveStmt * node ) {
     675template< typename core_t >
     676const ast::Stmt * ast::Pass< core_t >::visit( const ast::DirectiveStmt * node ) {
    658677        VISIT_START( node )
    659678
     
    663682//--------------------------------------------------------------------------
    664683// IfStmt
    665 template< typename pass_t >
    666 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::IfStmt * node ) {
     684template< typename core_t >
     685const ast::Stmt * ast::Pass< core_t >::visit( const ast::IfStmt * node ) {
    667686        VISIT_START( node );
    668687
     
    681700//--------------------------------------------------------------------------
    682701// WhileStmt
    683 template< typename pass_t >
    684 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::WhileStmt * node ) {
     702template< typename core_t >
     703const ast::Stmt * ast::Pass< core_t >::visit( const ast::WhileStmt * node ) {
    685704        VISIT_START( node );
    686705
     
    698717//--------------------------------------------------------------------------
    699718// ForStmt
    700 template< typename pass_t >
    701 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ForStmt * node ) {
     719template< typename core_t >
     720const ast::Stmt * ast::Pass< core_t >::visit( const ast::ForStmt * node ) {
    702721        VISIT_START( node );
    703722
     
    716735//--------------------------------------------------------------------------
    717736// SwitchStmt
    718 template< typename pass_t >
    719 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::SwitchStmt * node ) {
     737template< typename core_t >
     738const ast::Stmt * ast::Pass< core_t >::visit( const ast::SwitchStmt * node ) {
    720739        VISIT_START( node );
    721740
     
    730749//--------------------------------------------------------------------------
    731750// CaseStmt
    732 template< typename pass_t >
    733 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::CaseStmt * node ) {
     751template< typename core_t >
     752const ast::Stmt * ast::Pass< core_t >::visit( const ast::CaseStmt * node ) {
    734753        VISIT_START( node );
    735754
     
    744763//--------------------------------------------------------------------------
    745764// BranchStmt
    746 template< typename pass_t >
    747 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::BranchStmt * node ) {
     765template< typename core_t >
     766const ast::Stmt * ast::Pass< core_t >::visit( const ast::BranchStmt * node ) {
    748767        VISIT_START( node );
    749768        VISIT_END( Stmt, node );
     
    752771//--------------------------------------------------------------------------
    753772// ReturnStmt
    754 template< typename pass_t >
    755 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ReturnStmt * node ) {
     773template< typename core_t >
     774const ast::Stmt * ast::Pass< core_t >::visit( const ast::ReturnStmt * node ) {
    756775        VISIT_START( node );
    757776
     
    765784//--------------------------------------------------------------------------
    766785// ThrowStmt
    767 template< typename pass_t >
    768 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ThrowStmt * node ) {
     786template< typename core_t >
     787const ast::Stmt * ast::Pass< core_t >::visit( const ast::ThrowStmt * node ) {
    769788        VISIT_START( node );
    770789
     
    779798//--------------------------------------------------------------------------
    780799// TryStmt
    781 template< typename pass_t >
    782 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::TryStmt * node ) {
     800template< typename core_t >
     801const ast::Stmt * ast::Pass< core_t >::visit( const ast::TryStmt * node ) {
    783802        VISIT_START( node );
    784803
     
    794813//--------------------------------------------------------------------------
    795814// CatchStmt
    796 template< typename pass_t >
    797 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::CatchStmt * node ) {
     815template< typename core_t >
     816const ast::Stmt * ast::Pass< core_t >::visit( const ast::CatchStmt * node ) {
    798817        VISIT_START( node );
    799818
     
    811830//--------------------------------------------------------------------------
    812831// FinallyStmt
    813 template< typename pass_t >
    814 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::FinallyStmt * node ) {
     832template< typename core_t >
     833const ast::Stmt * ast::Pass< core_t >::visit( const ast::FinallyStmt * node ) {
    815834        VISIT_START( node );
    816835
     
    824843//--------------------------------------------------------------------------
    825844// FinallyStmt
    826 template< typename pass_t >
    827 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::SuspendStmt * node ) {
     845template< typename core_t >
     846const ast::Stmt * ast::Pass< core_t >::visit( const ast::SuspendStmt * node ) {
    828847        VISIT_START( node );
    829848
     
    837856//--------------------------------------------------------------------------
    838857// WaitForStmt
    839 template< typename pass_t >
    840 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::WaitForStmt * node ) {
     858template< typename core_t >
     859const ast::Stmt * ast::Pass< core_t >::visit( const ast::WaitForStmt * node ) {
    841860        VISIT_START( node );
    842861                // for( auto & clause : node->clauses ) {
     
    906925//--------------------------------------------------------------------------
    907926// WithStmt
    908 template< typename pass_t >
    909 const ast::Decl * ast::Pass< pass_t >::visit( const ast::WithStmt * node ) {
     927template< typename core_t >
     928const ast::Decl * ast::Pass< core_t >::visit( const ast::WithStmt * node ) {
    910929        VISIT_START( node );
    911930
     
    915934                        // catch statements introduce a level of scope (for the caught exception)
    916935                        guard_symtab guard { *this };
    917                         __pass::symtab::addWith( pass, 0, node->exprs, node );
     936                        __pass::symtab::addWith( core, 0, node->exprs, node );
    918937                        maybe_accept( node, &WithStmt::stmt );
    919938                }
     
    924943//--------------------------------------------------------------------------
    925944// NullStmt
    926 template< typename pass_t >
    927 const ast::NullStmt * ast::Pass< pass_t >::visit( const ast::NullStmt * node ) {
     945template< typename core_t >
     946const ast::NullStmt * ast::Pass< core_t >::visit( const ast::NullStmt * node ) {
    928947        VISIT_START( node );
    929948        VISIT_END( NullStmt, node );
     
    932951//--------------------------------------------------------------------------
    933952// DeclStmt
    934 template< typename pass_t >
    935 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::DeclStmt * node ) {
     953template< typename core_t >
     954const ast::Stmt * ast::Pass< core_t >::visit( const ast::DeclStmt * node ) {
    936955        VISIT_START( node );
    937956
     
    945964//--------------------------------------------------------------------------
    946965// ImplicitCtorDtorStmt
    947 template< typename pass_t >
    948 const ast::Stmt * ast::Pass< pass_t >::visit( const ast::ImplicitCtorDtorStmt * node ) {
     966template< typename core_t >
     967const ast::Stmt * ast::Pass< core_t >::visit( const ast::ImplicitCtorDtorStmt * node ) {
    949968        VISIT_START( node );
    950969
    951970        // For now this isn't visited, it is unclear if this causes problem
    952971        // if all tests are known to pass, remove this code
    953         // VISIT(
    954         //      maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
    955         // )
     972        VISIT(
     973                maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
     974        )
    956975
    957976        VISIT_END( Stmt, node );
     
    960979//--------------------------------------------------------------------------
    961980// ApplicationExpr
    962 template< typename pass_t >
    963 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ApplicationExpr * node ) {
     981template< typename core_t >
     982const ast::Expr * ast::Pass< core_t >::visit( const ast::ApplicationExpr * node ) {
    964983        VISIT_START( node );
    965984
     
    978997//--------------------------------------------------------------------------
    979998// UntypedExpr
    980 template< typename pass_t >
    981 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedExpr * node ) {
     999template< typename core_t >
     1000const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedExpr * node ) {
    9821001        VISIT_START( node );
    9831002
     
    9961015//--------------------------------------------------------------------------
    9971016// NameExpr
    998 template< typename pass_t >
    999 const ast::Expr * ast::Pass< pass_t >::visit( const ast::NameExpr * node ) {
     1017template< typename core_t >
     1018const ast::Expr * ast::Pass< core_t >::visit( const ast::NameExpr * node ) {
    10001019        VISIT_START( node );
    10011020
     
    10101029//--------------------------------------------------------------------------
    10111030// CastExpr
    1012 template< typename pass_t >
    1013 const ast::Expr * ast::Pass< pass_t >::visit( const ast::CastExpr * node ) {
     1031template< typename core_t >
     1032const ast::Expr * ast::Pass< core_t >::visit( const ast::CastExpr * node ) {
    10141033        VISIT_START( node );
    10151034
     
    10261045//--------------------------------------------------------------------------
    10271046// KeywordCastExpr
    1028 template< typename pass_t >
    1029 const ast::Expr * ast::Pass< pass_t >::visit( const ast::KeywordCastExpr * node ) {
     1047template< typename core_t >
     1048const ast::Expr * ast::Pass< core_t >::visit( const ast::KeywordCastExpr * node ) {
    10301049        VISIT_START( node );
    10311050
     
    10421061//--------------------------------------------------------------------------
    10431062// VirtualCastExpr
    1044 template< typename pass_t >
    1045 const ast::Expr * ast::Pass< pass_t >::visit( const ast::VirtualCastExpr * node ) {
     1063template< typename core_t >
     1064const ast::Expr * ast::Pass< core_t >::visit( const ast::VirtualCastExpr * node ) {
    10461065        VISIT_START( node );
    10471066
     
    10581077//--------------------------------------------------------------------------
    10591078// AddressExpr
    1060 template< typename pass_t >
    1061 const ast::Expr * ast::Pass< pass_t >::visit( const ast::AddressExpr * node ) {
     1079template< typename core_t >
     1080const ast::Expr * ast::Pass< core_t >::visit( const ast::AddressExpr * node ) {
    10621081        VISIT_START( node );
    10631082
     
    10741093//--------------------------------------------------------------------------
    10751094// LabelAddressExpr
    1076 template< typename pass_t >
    1077 const ast::Expr * ast::Pass< pass_t >::visit( const ast::LabelAddressExpr * node ) {
     1095template< typename core_t >
     1096const ast::Expr * ast::Pass< core_t >::visit( const ast::LabelAddressExpr * node ) {
    10781097        VISIT_START( node );
    10791098
     
    10881107//--------------------------------------------------------------------------
    10891108// UntypedMemberExpr
    1090 template< typename pass_t >
    1091 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedMemberExpr * node ) {
     1109template< typename core_t >
     1110const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedMemberExpr * node ) {
    10921111        VISIT_START( node );
    10931112
     
    11051124//--------------------------------------------------------------------------
    11061125// MemberExpr
    1107 template< typename pass_t >
    1108 const ast::Expr * ast::Pass< pass_t >::visit( const ast::MemberExpr * node ) {
     1126template< typename core_t >
     1127const ast::Expr * ast::Pass< core_t >::visit( const ast::MemberExpr * node ) {
    11091128        VISIT_START( node );
    11101129
     
    11211140//--------------------------------------------------------------------------
    11221141// VariableExpr
    1123 template< typename pass_t >
    1124 const ast::Expr * ast::Pass< pass_t >::visit( const ast::VariableExpr * node ) {
     1142template< typename core_t >
     1143const ast::Expr * ast::Pass< core_t >::visit( const ast::VariableExpr * node ) {
    11251144        VISIT_START( node );
    11261145
     
    11351154//--------------------------------------------------------------------------
    11361155// ConstantExpr
    1137 template< typename pass_t >
    1138 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConstantExpr * node ) {
     1156template< typename core_t >
     1157const ast::Expr * ast::Pass< core_t >::visit( const ast::ConstantExpr * node ) {
    11391158        VISIT_START( node );
    11401159
     
    11491168//--------------------------------------------------------------------------
    11501169// SizeofExpr
    1151 template< typename pass_t >
    1152 const ast::Expr * ast::Pass< pass_t >::visit( const ast::SizeofExpr * node ) {
     1170template< typename core_t >
     1171const ast::Expr * ast::Pass< core_t >::visit( const ast::SizeofExpr * node ) {
    11531172        VISIT_START( node );
    11541173
     
    11691188//--------------------------------------------------------------------------
    11701189// AlignofExpr
    1171 template< typename pass_t >
    1172 const ast::Expr * ast::Pass< pass_t >::visit( const ast::AlignofExpr * node ) {
     1190template< typename core_t >
     1191const ast::Expr * ast::Pass< core_t >::visit( const ast::AlignofExpr * node ) {
    11731192        VISIT_START( node );
    11741193
     
    11891208//--------------------------------------------------------------------------
    11901209// UntypedOffsetofExpr
    1191 template< typename pass_t >
    1192 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedOffsetofExpr * node ) {
     1210template< typename core_t >
     1211const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedOffsetofExpr * node ) {
    11931212        VISIT_START( node );
    11941213
     
    12051224//--------------------------------------------------------------------------
    12061225// OffsetofExpr
    1207 template< typename pass_t >
    1208 const ast::Expr * ast::Pass< pass_t >::visit( const ast::OffsetofExpr * node ) {
     1226template< typename core_t >
     1227const ast::Expr * ast::Pass< core_t >::visit( const ast::OffsetofExpr * node ) {
    12091228        VISIT_START( node );
    12101229
     
    12211240//--------------------------------------------------------------------------
    12221241// OffsetPackExpr
    1223 template< typename pass_t >
    1224 const ast::Expr * ast::Pass< pass_t >::visit( const ast::OffsetPackExpr * node ) {
     1242template< typename core_t >
     1243const ast::Expr * ast::Pass< core_t >::visit( const ast::OffsetPackExpr * node ) {
    12251244        VISIT_START( node );
    12261245
     
    12371256//--------------------------------------------------------------------------
    12381257// LogicalExpr
    1239 template< typename pass_t >
    1240 const ast::Expr * ast::Pass< pass_t >::visit( const ast::LogicalExpr * node ) {
     1258template< typename core_t >
     1259const ast::Expr * ast::Pass< core_t >::visit( const ast::LogicalExpr * node ) {
    12411260        VISIT_START( node );
    12421261
     
    12541273//--------------------------------------------------------------------------
    12551274// ConditionalExpr
    1256 template< typename pass_t >
    1257 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConditionalExpr * node ) {
     1275template< typename core_t >
     1276const ast::Expr * ast::Pass< core_t >::visit( const ast::ConditionalExpr * node ) {
    12581277        VISIT_START( node );
    12591278
     
    12721291//--------------------------------------------------------------------------
    12731292// CommaExpr
    1274 template< typename pass_t >
    1275 const ast::Expr * ast::Pass< pass_t >::visit( const ast::CommaExpr * node ) {
     1293template< typename core_t >
     1294const ast::Expr * ast::Pass< core_t >::visit( const ast::CommaExpr * node ) {
    12761295        VISIT_START( node );
    12771296
     
    12891308//--------------------------------------------------------------------------
    12901309// TypeExpr
    1291 template< typename pass_t >
    1292 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TypeExpr * node ) {
     1310template< typename core_t >
     1311const ast::Expr * ast::Pass< core_t >::visit( const ast::TypeExpr * node ) {
    12931312        VISIT_START( node );
    12941313
     
    13051324//--------------------------------------------------------------------------
    13061325// AsmExpr
    1307 template< typename pass_t >
    1308 const ast::Expr * ast::Pass< pass_t >::visit( const ast::AsmExpr * node ) {
     1326template< typename core_t >
     1327const ast::Expr * ast::Pass< core_t >::visit( const ast::AsmExpr * node ) {
    13091328        VISIT_START( node );
    13101329
     
    13221341//--------------------------------------------------------------------------
    13231342// ImplicitCopyCtorExpr
    1324 template< typename pass_t >
    1325 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ImplicitCopyCtorExpr * node ) {
     1343template< typename core_t >
     1344const ast::Expr * ast::Pass< core_t >::visit( const ast::ImplicitCopyCtorExpr * node ) {
    13261345        VISIT_START( node );
    13271346
     
    13381357//--------------------------------------------------------------------------
    13391358// ConstructorExpr
    1340 template< typename pass_t >
    1341 const ast::Expr * ast::Pass< pass_t >::visit( const ast::ConstructorExpr * node ) {
     1359template< typename core_t >
     1360const ast::Expr * ast::Pass< core_t >::visit( const ast::ConstructorExpr * node ) {
    13421361        VISIT_START( node );
    13431362
     
    13541373//--------------------------------------------------------------------------
    13551374// CompoundLiteralExpr
    1356 template< typename pass_t >
    1357 const ast::Expr * ast::Pass< pass_t >::visit( const ast::CompoundLiteralExpr * node ) {
     1375template< typename core_t >
     1376const ast::Expr * ast::Pass< core_t >::visit( const ast::CompoundLiteralExpr * node ) {
    13581377        VISIT_START( node );
    13591378
     
    13701389//--------------------------------------------------------------------------
    13711390// RangeExpr
    1372 template< typename pass_t >
    1373 const ast::Expr * ast::Pass< pass_t >::visit( const ast::RangeExpr * node ) {
     1391template< typename core_t >
     1392const ast::Expr * ast::Pass< core_t >::visit( const ast::RangeExpr * node ) {
    13741393        VISIT_START( node );
    13751394
     
    13871406//--------------------------------------------------------------------------
    13881407// UntypedTupleExpr
    1389 template< typename pass_t >
    1390 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedTupleExpr * node ) {
     1408template< typename core_t >
     1409const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedTupleExpr * node ) {
    13911410        VISIT_START( node );
    13921411
     
    14031422//--------------------------------------------------------------------------
    14041423// TupleExpr
    1405 template< typename pass_t >
    1406 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleExpr * node ) {
     1424template< typename core_t >
     1425const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleExpr * node ) {
    14071426        VISIT_START( node );
    14081427
     
    14191438//--------------------------------------------------------------------------
    14201439// TupleIndexExpr
    1421 template< typename pass_t >
    1422 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleIndexExpr * node ) {
     1440template< typename core_t >
     1441const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleIndexExpr * node ) {
    14231442        VISIT_START( node );
    14241443
     
    14351454//--------------------------------------------------------------------------
    14361455// TupleAssignExpr
    1437 template< typename pass_t >
    1438 const ast::Expr * ast::Pass< pass_t >::visit( const ast::TupleAssignExpr * node ) {
     1456template< typename core_t >
     1457const ast::Expr * ast::Pass< core_t >::visit( const ast::TupleAssignExpr * node ) {
    14391458        VISIT_START( node );
    14401459
     
    14511470//--------------------------------------------------------------------------
    14521471// StmtExpr
    1453 template< typename pass_t >
    1454 const ast::Expr * ast::Pass< pass_t >::visit( const ast::StmtExpr * node ) {
     1472template< typename core_t >
     1473const ast::Expr * ast::Pass< core_t >::visit( const ast::StmtExpr * node ) {
    14551474        VISIT_START( node );
    14561475
    14571476        VISIT(// don't want statements from outer CompoundStmts to be added to this StmtExpr
    14581477                // get the stmts that will need to be spliced in
    1459                 auto stmts_before = __pass::stmtsToAddBefore( pass, 0);
    1460                 auto stmts_after  = __pass::stmtsToAddAfter ( pass, 0);
     1478                auto stmts_before = __pass::stmtsToAddBefore( core, 0);
     1479                auto stmts_after  = __pass::stmtsToAddAfter ( core, 0);
    14611480
    14621481                // These may be modified by subnode but most be restored once we exit this statemnet.
    1463                 ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::env( pass, 0) );
     1482                ValueGuardPtr< const ast::TypeSubstitution * > __old_env( __pass::env( core, 0) );
    14641483                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
    14651484                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
     
    14791498//--------------------------------------------------------------------------
    14801499// UniqueExpr
    1481 template< typename pass_t >
    1482 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UniqueExpr * node ) {
     1500template< typename core_t >
     1501const ast::Expr * ast::Pass< core_t >::visit( const ast::UniqueExpr * node ) {
    14831502        VISIT_START( node );
    14841503
     
    14951514//--------------------------------------------------------------------------
    14961515// UntypedInitExpr
    1497 template< typename pass_t >
    1498 const ast::Expr * ast::Pass< pass_t >::visit( const ast::UntypedInitExpr * node ) {
     1516template< typename core_t >
     1517const ast::Expr * ast::Pass< core_t >::visit( const ast::UntypedInitExpr * node ) {
    14991518        VISIT_START( node );
    15001519
     
    15121531//--------------------------------------------------------------------------
    15131532// InitExpr
    1514 template< typename pass_t >
    1515 const ast::Expr * ast::Pass< pass_t >::visit( const ast::InitExpr * node ) {
     1533template< typename core_t >
     1534const ast::Expr * ast::Pass< core_t >::visit( const ast::InitExpr * node ) {
    15161535        VISIT_START( node );
    15171536
     
    15291548//--------------------------------------------------------------------------
    15301549// DeletedExpr
    1531 template< typename pass_t >
    1532 const ast::Expr * ast::Pass< pass_t >::visit( const ast::DeletedExpr * node ) {
     1550template< typename core_t >
     1551const ast::Expr * ast::Pass< core_t >::visit( const ast::DeletedExpr * node ) {
    15331552        VISIT_START( node );
    15341553
     
    15461565//--------------------------------------------------------------------------
    15471566// DefaultArgExpr
    1548 template< typename pass_t >
    1549 const ast::Expr * ast::Pass< pass_t >::visit( const ast::DefaultArgExpr * node ) {
     1567template< typename core_t >
     1568const ast::Expr * ast::Pass< core_t >::visit( const ast::DefaultArgExpr * node ) {
    15501569        VISIT_START( node );
    15511570
     
    15621581//--------------------------------------------------------------------------
    15631582// GenericExpr
    1564 template< typename pass_t >
    1565 const ast::Expr * ast::Pass< pass_t >::visit( const ast::GenericExpr * node ) {
     1583template< typename core_t >
     1584const ast::Expr * ast::Pass< core_t >::visit( const ast::GenericExpr * node ) {
    15661585        VISIT_START( node );
    15671586
     
    16021621//--------------------------------------------------------------------------
    16031622// VoidType
    1604 template< typename pass_t >
    1605 const ast::Type * ast::Pass< pass_t >::visit( const ast::VoidType * node ) {
     1623template< typename core_t >
     1624const ast::Type * ast::Pass< core_t >::visit( const ast::VoidType * node ) {
    16061625        VISIT_START( node );
    16071626
     
    16111630//--------------------------------------------------------------------------
    16121631// BasicType
    1613 template< typename pass_t >
    1614 const ast::Type * ast::Pass< pass_t >::visit( const ast::BasicType * node ) {
     1632template< typename core_t >
     1633const ast::Type * ast::Pass< core_t >::visit( const ast::BasicType * node ) {
    16151634        VISIT_START( node );
    16161635
     
    16201639//--------------------------------------------------------------------------
    16211640// PointerType
    1622 template< typename pass_t >
    1623 const ast::Type * ast::Pass< pass_t >::visit( const ast::PointerType * node ) {
     1641template< typename core_t >
     1642const ast::Type * ast::Pass< core_t >::visit( const ast::PointerType * node ) {
    16241643        VISIT_START( node );
    16251644
     
    16341653//--------------------------------------------------------------------------
    16351654// ArrayType
    1636 template< typename pass_t >
    1637 const ast::Type * ast::Pass< pass_t >::visit( const ast::ArrayType * node ) {
     1655template< typename core_t >
     1656const ast::Type * ast::Pass< core_t >::visit( const ast::ArrayType * node ) {
    16381657        VISIT_START( node );
    16391658
     
    16481667//--------------------------------------------------------------------------
    16491668// ReferenceType
    1650 template< typename pass_t >
    1651 const ast::Type * ast::Pass< pass_t >::visit( const ast::ReferenceType * node ) {
     1669template< typename core_t >
     1670const ast::Type * ast::Pass< core_t >::visit( const ast::ReferenceType * node ) {
    16521671        VISIT_START( node );
    16531672
     
    16611680//--------------------------------------------------------------------------
    16621681// QualifiedType
    1663 template< typename pass_t >
    1664 const ast::Type * ast::Pass< pass_t >::visit( const ast::QualifiedType * node ) {
     1682template< typename core_t >
     1683const ast::Type * ast::Pass< core_t >::visit( const ast::QualifiedType * node ) {
    16651684        VISIT_START( node );
    16661685
     
    16751694//--------------------------------------------------------------------------
    16761695// FunctionType
    1677 template< typename pass_t >
    1678 const ast::Type * ast::Pass< pass_t >::visit( const ast::FunctionType * node ) {
    1679         VISIT_START( node );
    1680 
    1681         VISIT(
    1682                 maybe_accept( node, &FunctionType::forall  );
     1696template< typename core_t >
     1697const 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 );
    16831703                maybe_accept( node, &FunctionType::returns );
    16841704                maybe_accept( node, &FunctionType::params  );
    1685         )
     1705        })
    16861706
    16871707        VISIT_END( Type, node );
     
    16901710//--------------------------------------------------------------------------
    16911711// StructInstType
    1692 template< typename pass_t >
    1693 const ast::Type * ast::Pass< pass_t >::visit( const ast::StructInstType * node ) {
    1694         VISIT_START( node );
    1695 
    1696         __pass::symtab::addStruct( pass, 0, node->name );
     1712template< typename core_t >
     1713const ast::Type * ast::Pass< core_t >::visit( const ast::StructInstType * node ) {
     1714        VISIT_START( node );
     1715
     1716        __pass::symtab::addStruct( core, 0, node->name );
    16971717
    16981718        VISIT({
    16991719                guard_symtab guard { *this };
    1700                 maybe_accept( node, &StructInstType::forall );
     1720                guard_forall_subs forall_guard { *this, node };
     1721                mutate_forall( node );
    17011722                maybe_accept( node, &StructInstType::params );
    17021723        })
     
    17071728//--------------------------------------------------------------------------
    17081729// UnionInstType
    1709 template< typename pass_t >
    1710 const 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         {
     1730template< typename core_t >
     1731const 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({
    17161737                guard_symtab guard { *this };
    1717                 maybe_accept( node, &UnionInstType::forall );
     1738                guard_forall_subs forall_guard { *this, node };
     1739                mutate_forall( node );
    17181740                maybe_accept( node, &UnionInstType::params );
    1719         }
     1741        })
    17201742
    17211743        VISIT_END( Type, node );
     
    17241746//--------------------------------------------------------------------------
    17251747// EnumInstType
    1726 template< typename pass_t >
    1727 const ast::Type * ast::Pass< pass_t >::visit( const ast::EnumInstType * node ) {
    1728         VISIT_START( node );
    1729 
    1730         VISIT(
    1731                 maybe_accept( node, &EnumInstType::forall );
     1748template< typename core_t >
     1749const 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 );
    17321755                maybe_accept( node, &EnumInstType::params );
    1733         )
     1756        })
    17341757
    17351758        VISIT_END( Type, node );
     
    17381761//--------------------------------------------------------------------------
    17391762// TraitInstType
    1740 template< typename pass_t >
    1741 const ast::Type * ast::Pass< pass_t >::visit( const ast::TraitInstType * node ) {
    1742         VISIT_START( node );
    1743 
    1744         VISIT(
    1745                 maybe_accept( node, &TraitInstType::forall );
     1763template< typename core_t >
     1764const 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 );
    17461770                maybe_accept( node, &TraitInstType::params );
    1747         )
     1771        })
    17481772
    17491773        VISIT_END( Type, node );
     
    17521776//--------------------------------------------------------------------------
    17531777// TypeInstType
    1754 template< typename pass_t >
    1755 const 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 );
     1778template< typename core_t >
     1779const 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 );
    17611790        )
    17621791
     
    17661795//--------------------------------------------------------------------------
    17671796// TupleType
    1768 template< typename pass_t >
    1769 const ast::Type * ast::Pass< pass_t >::visit( const ast::TupleType * node ) {
     1797template< typename core_t >
     1798const ast::Type * ast::Pass< core_t >::visit( const ast::TupleType * node ) {
    17701799        VISIT_START( node );
    17711800
     
    17801809//--------------------------------------------------------------------------
    17811810// TypeofType
    1782 template< typename pass_t >
    1783 const ast::Type * ast::Pass< pass_t >::visit( const ast::TypeofType * node ) {
     1811template< typename core_t >
     1812const ast::Type * ast::Pass< core_t >::visit( const ast::TypeofType * node ) {
    17841813        VISIT_START( node );
    17851814
     
    17931822//--------------------------------------------------------------------------
    17941823// VarArgsType
    1795 template< typename pass_t >
    1796 const ast::Type * ast::Pass< pass_t >::visit( const ast::VarArgsType * node ) {
     1824template< typename core_t >
     1825const ast::Type * ast::Pass< core_t >::visit( const ast::VarArgsType * node ) {
    17971826        VISIT_START( node );
    17981827
     
    18021831//--------------------------------------------------------------------------
    18031832// ZeroType
    1804 template< typename pass_t >
    1805 const ast::Type * ast::Pass< pass_t >::visit( const ast::ZeroType * node ) {
     1833template< typename core_t >
     1834const ast::Type * ast::Pass< core_t >::visit( const ast::ZeroType * node ) {
    18061835        VISIT_START( node );
    18071836
     
    18111840//--------------------------------------------------------------------------
    18121841// OneType
    1813 template< typename pass_t >
    1814 const ast::Type * ast::Pass< pass_t >::visit( const ast::OneType * node ) {
     1842template< typename core_t >
     1843const ast::Type * ast::Pass< core_t >::visit( const ast::OneType * node ) {
    18151844        VISIT_START( node );
    18161845
     
    18201849//--------------------------------------------------------------------------
    18211850// GlobalScopeType
    1822 template< typename pass_t >
    1823 const ast::Type * ast::Pass< pass_t >::visit( const ast::GlobalScopeType * node ) {
     1851template< typename core_t >
     1852const ast::Type * ast::Pass< core_t >::visit( const ast::GlobalScopeType * node ) {
    18241853        VISIT_START( node );
    18251854
     
    18301859//--------------------------------------------------------------------------
    18311860// Designation
    1832 template< typename pass_t >
    1833 const ast::Designation * ast::Pass< pass_t >::visit( const ast::Designation * node ) {
     1861template< typename core_t >
     1862const ast::Designation * ast::Pass< core_t >::visit( const ast::Designation * node ) {
    18341863        VISIT_START( node );
    18351864
     
    18411870//--------------------------------------------------------------------------
    18421871// SingleInit
    1843 template< typename pass_t >
    1844 const ast::Init * ast::Pass< pass_t >::visit( const ast::SingleInit * node ) {
     1872template< typename core_t >
     1873const ast::Init * ast::Pass< core_t >::visit( const ast::SingleInit * node ) {
    18451874        VISIT_START( node );
    18461875
     
    18541883//--------------------------------------------------------------------------
    18551884// ListInit
    1856 template< typename pass_t >
    1857 const ast::Init * ast::Pass< pass_t >::visit( const ast::ListInit * node ) {
     1885template< typename core_t >
     1886const ast::Init * ast::Pass< core_t >::visit( const ast::ListInit * node ) {
    18581887        VISIT_START( node );
    18591888
     
    18681897//--------------------------------------------------------------------------
    18691898// ConstructorInit
    1870 template< typename pass_t >
    1871 const ast::Init * ast::Pass< pass_t >::visit( const ast::ConstructorInit * node ) {
     1899template< typename core_t >
     1900const ast::Init * ast::Pass< core_t >::visit( const ast::ConstructorInit * node ) {
    18721901        VISIT_START( node );
    18731902
     
    18831912//--------------------------------------------------------------------------
    18841913// Attribute
    1885 template< typename pass_t >
    1886 const ast::Attribute * ast::Pass< pass_t >::visit( const ast::Attribute * node  )  {
     1914template< typename core_t >
     1915const ast::Attribute * ast::Pass< core_t >::visit( const ast::Attribute * node  )  {
    18871916        VISIT_START( node );
    18881917
     
    18961925//--------------------------------------------------------------------------
    18971926// TypeSubstitution
    1898 template< typename pass_t >
    1899 const ast::TypeSubstitution * ast::Pass< pass_t >::visit( const ast::TypeSubstitution * node ) {
     1927template< typename core_t >
     1928const ast::TypeSubstitution * ast::Pass< core_t >::visit( const ast::TypeSubstitution * node ) {
    19001929        VISIT_START( node );
    19011930
     
    19071936                                guard_symtab guard { *this };
    19081937                                auto new_node = p.second->accept( *this );
    1909                                 if (new_node != p.second) mutated = false;
     1938                                if (new_node != p.second) mutated = true;
    19101939                                new_map.insert({ p.first, new_node });
    19111940                        }
     
    19231952                                guard_symtab guard { *this };
    19241953                                auto new_node = p.second->accept( *this );
    1925                                 if (new_node != p.second) mutated = false;
     1954                                if (new_node != p.second) mutated = true;
    19261955                                new_map.insert({ p.first, new_node });
    19271956                        }
  • src/AST/Pass.proto.hpp

    r309d814 r4c925cd  
    1717// IWYU pragma: private, include "Pass.hpp"
    1818
     19#include "Common/Stats/Heap.h"
     20
    1921namespace ast {
    20 template<typename pass_type>
     22template<typename core_t>
    2123class Pass;
    2224
     
    8284                };
    8385
    84                 std::stack< cleanup_t > cleanups;
     86                std::stack< cleanup_t, std::vector<cleanup_t> > cleanups;
    8587        };
    8688
     
    111113        /// "Short hand" to check if this is a valid previsit function
    112114        /// Mostly used to make the static_assert look (and print) prettier
    113         template<typename pass_t, typename node_t>
     115        template<typename core_t, typename node_t>
    114116        struct is_valid_previsit {
    115                 using ret_t = decltype( ((pass_t*)nullptr)->previsit( (const node_t *)nullptr ) );
     117                using ret_t = decltype( ((core_t*)nullptr)->previsit( (const node_t *)nullptr ) );
    116118
    117119                static constexpr bool value = std::is_void< ret_t >::value ||
     
    127129        template<>
    128130        struct __assign<true> {
    129                 template<typename pass_t, typename node_t>
    130                 static inline void result( pass_t & pass, const node_t * & node ) {
    131                         pass.previsit( node );
     131                template<typename core_t, typename node_t>
     132                static inline void result( core_t & core, const node_t * & node ) {
     133                        core.previsit( node );
    132134                }
    133135        };
     
    135137        template<>
    136138        struct __assign<false> {
    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 );
     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 );
    140142                        assertf(node, "Previsit must not return NULL");
    141143                }
     
    150152        template<>
    151153        struct __return<true> {
    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 );
     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 );
    155157                        return node;
    156158                }
     
    159161        template<>
    160162        struct __return<false> {
    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 );
     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 );
    164166                }
    165167        };
     
    180182        //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    181183        // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call
    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() ) {
     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() ) {
    184186                static_assert(
    185                         is_valid_previsit<pass_t, node_t>::value,
     187                        is_valid_previsit<core_t, node_t>::value,
    186188                        "Previsit may not change the type of the node. It must return its paremeter or void."
    187189                );
     
    189191                __assign<
    190192                        std::is_void<
    191                                 decltype( pass.previsit( node ) )
     193                                decltype( core.previsit( node ) )
    192194                        >::value
    193                 >::result( pass, node );
     195                >::result( core, node );
    194196        }
    195197
    196         template<typename pass_t, typename node_t>
    197         static inline auto previsit( pass_t &, const node_t *, long ) {}
     198        template<typename core_t, typename node_t>
     199        static inline auto previsit( core_t &, const node_t *, long ) {}
    198200
    199201        // PostVisit : never mutates the passed pointer but may return a different node
    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 ) )
     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 ) )
    203205        {
    204206                return __return<
    205207                        std::is_void<
    206                                 decltype( pass.postvisit( node ) )
     208                                decltype( core.postvisit( node ) )
    207209                        >::value
    208                 >::result( pass, node );
     210                >::result( core, node );
    209211        }
    210212
    211         template<typename pass_t, typename node_t>
    212         static inline const node_t * postvisit( pass_t &, const node_t * node, long ) { return node; }
     213        template<typename core_t, typename node_t>
     214        static inline const node_t * postvisit( core_t &, const node_t * node, long ) { return node; }
    213215
    214216        //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     
    225227        // The type is not strictly enforced but does match the accessory
    226228        #define FIELD_PTR( name, default_type ) \
    227         template< typename pass_t > \
    228         static inline auto name( pass_t & pass, int ) -> decltype( &pass.name ) { return &pass.name; } \
     229        template< typename core_t > \
     230        static inline auto name( core_t & core, int ) -> decltype( &core.name ) { return &core.name; } \
    229231        \
    230         template< typename pass_t > \
    231         static inline default_type * name( pass_t &, long ) { return nullptr; }
     232        template< typename core_t > \
     233        static inline default_type * name( core_t &, long ) { return nullptr; }
    232234
    233235        // List of fields and their expected types
     
    239241        FIELD_PTR( visit_children, __pass::bool_ref )
    240242        FIELD_PTR( at_cleanup, __pass::at_cleanup_t )
    241         FIELD_PTR( visitor, ast::Pass<pass_t> * const )
     243        FIELD_PTR( visitor, ast::Pass<core_t> * const )
    242244
    243245        // Remove the macro to make sure we don't clash
    244246        #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) {}
    245263
    246264        // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement.
     
    248266        // detect it using the same strategy
    249267        namespace scope {
    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
     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
    268286        // detect the presence of a member name `symtab` and call all the members appropriately
    269287        namespace symtab {
    270288                // Some simple scoping rules
    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 ) {}
     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 ) {}
    286304
    287305                // The symbol table has 2 kind of functions mostly, 1 argument and 2 arguments
    288306                // Create macro to condense these common patterns
    289307                #define SYMTAB_FUNC1( func, type ) \
    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 ); \
     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 ); \
    293311                } \
    294312                \
    295                 template<typename pass_t> \
    296                 static inline void func( pass_t &, long, type ) {}
     313                template<typename core_t> \
     314                static inline void func( core_t &, long, type ) {}
    297315
    298316                #define SYMTAB_FUNC2( func, type1, type2 ) \
    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 ); \
     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 ); \
    302320                } \
    303321                        \
    304                 template<typename pass_t> \
    305                 static inline void func( pass_t &, long, type1, type2 ) {}
     322                template<typename core_t> \
     323                static inline void func( core_t &, long, type1, type2 ) {}
    306324
    307325                SYMTAB_FUNC1( addId     , const DeclWithType *  );
     
    311329                SYMTAB_FUNC1( addUnion  , const UnionDecl *     );
    312330                SYMTAB_FUNC1( addTrait  , const TraitDecl *     );
    313                 SYMTAB_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Node * );
     331                SYMTAB_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Decl * );
    314332
    315333                // A few extra functions have more complicated behaviour, they are hand written
    316                 template<typename pass_t>
    317                 static inline auto addStructFwd( pass_t & pass, int, const ast::StructDecl * decl ) -> decltype( pass.symtab.addStruct( decl ), void() ) {
     334                template<typename core_t>
     335                static inline auto addStructFwd( core_t & core, int, const ast::StructDecl * decl ) -> decltype( core.symtab.addStruct( decl ), void() ) {
    318336                        ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name );
    319337                        fwd->params = decl->params;
    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() ) {
     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() ) {
    328346                        UnionDecl * fwd = new UnionDecl( decl->location, decl->name );
    329347                        fwd->params = decl->params;
    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 );
     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 );
    340358                        }
    341359                }
    342360
    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 );
     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 );
    350368                        }
    351369                }
    352370
    353                 template<typename pass_t>
    354                 static inline void addUnion( pass_t &, long, const std::string & ) {}
     371                template<typename core_t>
     372                static inline void addUnion( core_t &, long, const std::string & ) {}
    355373
    356374                #undef SYMTAB_FUNC1
    357375                #undef SYMTAB_FUNC2
    358         };
    359 };
    360 };
     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
  • src/AST/Print.cpp

    r309d814 r4c925cd  
    2929
    3030template <typename C, typename... T>
    31 constexpr auto make_array(T&&... values) ->
    32         array<C,sizeof...(T)>
     31constexpr array<C,sizeof...(T)> make_array(T&&... values)
    3332{
    3433        return array<C,sizeof...(T)>{
     
    129128
    130129        void print( const ast::Expr::InferUnion & inferred, unsigned level = 0 ) {
    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()
     130                if (inferred.data.resnSlots && !inferred.data.resnSlots->empty()) {
     131                        os << indent << "with " << inferred.data.resnSlots->size()
    135132                           << " pending inference slots" << endl;
    136                         return;
    137                 }
    138                 case ast::Expr::InferUnion::Params: {
     133                }
     134                if (inferred.data.inferParams && !inferred.data.inferParams->empty()) {
    139135                        os << indent << "with inferred parameters " << level << ":" << endl;
    140136                        ++indent;
    141                         for ( const auto & i : inferred.data.inferParams ) {
     137                        for ( const auto & i : *inferred.data.inferParams ) {
    142138                                os << indent;
    143                                 short_print( Decl::fromId( i.second.decl ) );
     139                                short_print( i.second.declptr );
    144140                                os << endl;
    145141                                print( i.second.expr->inferred, level+1 );
    146142                        }
    147143                        --indent;
    148                         return;
    149                 }
    150144                }
    151145        }
     
    233227                }
    234228
    235                 if ( ! short_mode && ! node->assertions.empty() ) {
     229                if ( ! node->assertions.empty() ) {
    236230                        os << endl << indent << "... with assertions" << endl;
    237231                        ++indent;
     
    842836        virtual const ast::Expr * visit( const ast::CastExpr * node ) override final {
    843837                ++indent;
    844                 os << (node->isGenerated ? "Generated" : "Explicit") << " cast of:" << endl << indent;
     838                os << (node->isGenerated ? "Generated" : "Explicit") << " Cast of:" << endl << indent;
    845839                safe_print( node->arg );
    846840                os << endl << indent-1 << "... to:";
  • src/AST/Stmt.hpp

    r309d814 r4c925cd  
    2727
    2828// Must be included in *all* AST classes; should be #undef'd at the end of the file
    29 #define MUTATE_FRIEND template<typename node_t> friend node_t * mutate(const node_t * node);
     29#define MUTATE_FRIEND \
     30    template<typename node_t> friend node_t * mutate(const node_t * node); \
     31        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3032
    3133namespace ast {
     
    412414class ImplicitCtorDtorStmt final : public Stmt {
    413415public:
    414         readonly<Stmt> callStmt;
     416        ptr<Stmt> callStmt;
    415417
    416418        ImplicitCtorDtorStmt( const CodeLocation & loc, const Stmt * callStmt,
  • src/AST/Type.cpp

    r309d814 r4c925cd  
    99// Author           : Aaron B. Moss
    1010// Created On       : Mon May 13 15:00:00 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Dec 15 16:56:28 2019
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Jul 23 14:16:00 2020
     13// Update Count     : 5
    1414//
    1515
     
    2121
    2222#include "Decl.hpp"
     23#include "ForallSubstitutor.hpp" // for substituteForall
    2324#include "Init.hpp"
     25#include "Common/utility.h"      // for copy, move
    2426#include "InitTweak/InitTweak.h" // for getPointerBase
    2527#include "Tuples/Tuples.h"       // for isTtype
     
    9092// GENERATED END
    9193
     94// --- ParameterizedType
     95
     96void ParameterizedType::initWithSub(
     97        const ParameterizedType & o, Pass< ForallSubstitutor > & sub
     98) {
     99        forall = sub.core( o.forall );
     100}
     101
    92102// --- FunctionType
     103
     104FunctionType::FunctionType( const FunctionType & o )
     105: ParameterizedType( o.qualifiers, copy( o.attributes ) ), returns(), params(),
     106  isVarArgs( o.isVarArgs ) {
     107        Pass< ForallSubstitutor > sub;
     108        initWithSub( o, sub );           // initialize substitution map
     109        returns = sub.core( o.returns ); // apply to return and parameter types
     110        params = sub.core( o.params );
     111}
    93112
    94113namespace {
     
    106125
    107126// --- ReferenceToType
     127
     128void ReferenceToType::initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub ) {
     129        ParameterizedType::initWithSub( o, sub ); // initialize substitution
     130        params = sub.core( o.params );            // apply to parameters
     131}
     132
     133ReferenceToType::ReferenceToType( const ReferenceToType & o )
     134: ParameterizedType( o.qualifiers, copy( o.attributes ) ), params(), name( o.name ),
     135  hoistType( o.hoistType ) {
     136        Pass< ForallSubstitutor > sub;
     137        initWithSub( o, sub );
     138}
     139
    108140std::vector<readonly<Decl>> ReferenceToType::lookup( const std::string& name ) const {
    109141        assertf( aggr(), "Must have aggregate to perform lookup" );
     
    116148}
    117149
    118 // --- StructInstType
    119 
    120 StructInstType::StructInstType( const StructDecl * b, CV::Qualifiers q,
    121         std::vector<ptr<Attribute>>&& as )
    122 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
    123 
    124 bool StructInstType::isComplete() const { return base ? base->body : false; }
    125 
    126 // --- UnionInstType
    127 
    128 UnionInstType::UnionInstType( const UnionDecl * b, CV::Qualifiers q,
    129         std::vector<ptr<Attribute>>&& as )
    130 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
    131 
    132 bool UnionInstType::isComplete() const { return base ? base->body : false; }
    133 
    134 // --- EnumInstType
    135 
    136 EnumInstType::EnumInstType( const EnumDecl * b, CV::Qualifiers q,
    137         std::vector<ptr<Attribute>>&& as )
    138 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
    139 
    140 bool EnumInstType::isComplete() const { return base ? base->body : false; }
     150// --- SueInstType (StructInstType, UnionInstType, EnumInstType)
     151
     152template<typename decl_t>
     153SueInstType<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 ) {}
     156
     157template<typename decl_t>
     158bool SueInstType<decl_t>::isComplete() const {
     159        return base ? base->body : false;
     160}
     161
     162template class SueInstType<StructDecl>;
     163template class SueInstType<UnionDecl>;
     164template class SueInstType<EnumDecl>;
    141165
    142166// --- TraitInstType
    143167
    144 TraitInstType::TraitInstType( const TraitDecl * b, CV::Qualifiers q,
    145         std::vector<ptr<Attribute>>&& as )
    146 : ReferenceToType( b->name, q, std::move(as) ), base( b ) {}
     168TraitInstType::TraitInstType(
     169        const TraitDecl * b, CV::Qualifiers q, std::vector<ptr<Attribute>>&& as )
     170: ReferenceToType( b->name, q, move(as) ), base( b ) {}
    147171
    148172// --- TypeInstType
     173
     174TypeInstType::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}
    149180
    150181void TypeInstType::set_base( const TypeDecl * b ) {
     
    158189
    159190TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q )
    160 : Type( q ), types( std::move(ts) ), members() {
     191: Type( q ), types( move(ts) ), members() {
    161192        // This constructor is awkward. `TupleType` needs to contain objects so that members can be
    162193        // named, but members without initializer nodes end up getting constructors, which breaks
  • src/AST/Type.hpp

    r309d814 r4c925cd  
    99// Author           : Aaron B. Moss
    1010// Created On       : Thu May 9 10:00:00 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Dec 11 21:56:46 2019
    13 // Update Count     : 5
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Jul 23 14:15:00 2020
     13// Update Count     : 6
    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 template<typename node_t> friend node_t * mutate(const node_t * node);
     31#define MUTATE_FRIEND \
     32    template<typename node_t> friend node_t * mutate(const node_t * node); \
     33        template<typename node_t> friend node_t * shallowCopy(const node_t * node);
    3234
    3335namespace ast {
     36
     37template< typename T > class Pass;
     38
     39struct ForallSubstitutor;
    3440
    3541class Type : public Node {
     
    4450        bool is_volatile() const { return qualifiers.is_volatile; }
    4551        bool is_restrict() const { return qualifiers.is_restrict; }
    46         bool is_lvalue() const { return qualifiers.is_lvalue; }
    4752        bool is_mutex() const { return qualifiers.is_mutex; }
    4853        bool is_atomic() const { return qualifiers.is_atomic; }
     
    5156        Type * set_volatile( bool v ) { qualifiers.is_volatile = v; return this; }
    5257        Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; }
    53         Type * set_lvalue( bool v ) { qualifiers.is_lvalue = v; return this; }
    5458        Type * set_mutex( bool v ) { qualifiers.is_mutex = v; return this; }
    5559        Type * set_atomic( bool v ) { qualifiers.is_atomic = v; return this; }
     
    163167        static const char *typeNames[];
    164168
    165         BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} ) 
     169        BasicType( Kind k, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    166170        : Type(q, std::move(as)), kind(k) {}
    167171
     
    265269/// Base type for potentially forall-qualified types
    266270class ParameterizedType : public Type {
     271protected:
     272        /// initializes forall with substitutor
     273        void initWithSub( const ParameterizedType & o, Pass< ForallSubstitutor > & sub );
    267274public:
    268275        using ForallList = std::vector<ptr<TypeDecl>>;
     
    276283        ParameterizedType( CV::Qualifiers q, std::vector<ptr<Attribute>> && as = {} )
    277284        : Type(q, std::move(as)), forall() {}
     285
     286        // enforce use of ForallSubstitutor to copy parameterized type
     287        ParameterizedType( const ParameterizedType & ) = delete;
     288
     289        ParameterizedType( ParameterizedType && ) = default;
     290
     291        // no need to change destructor, and operator= deleted in Node
    278292
    279293private:
     
    301315        : ParameterizedType(q), returns(), params(), isVarArgs(va) {}
    302316
     317        FunctionType( const FunctionType & o );
     318
    303319        /// true if either the parameters or return values contain a tttype
    304320        bool isTtype() const;
     
    314330/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
    315331class ReferenceToType : public ParameterizedType {
     332protected:
     333        /// Initializes forall and parameters based on substitutor
     334        void initWithSub( const ReferenceToType & o, Pass< ForallSubstitutor > & sub );
    316335public:
    317336        std::vector<ptr<Expr>> params;
     
    319338        bool hoistType = false;
    320339
    321         ReferenceToType( const std::string& n, CV::Qualifiers q = {},
    322                 std::vector<ptr<Attribute>> && as = {} )
     340        ReferenceToType(
     341                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    323342        : ParameterizedType(q, std::move(as)), params(), name(n) {}
     343
     344        ReferenceToType( const ReferenceToType & o );
    324345
    325346        /// Gets aggregate declaration this type refers to
     
    333354};
    334355
    335 /// instance of struct type
    336 class StructInstType final : public ReferenceToType {
    337 public:
    338         readonly<StructDecl> base;
    339 
    340         StructInstType( const std::string& n, CV::Qualifiers q = {},
    341                 std::vector<ptr<Attribute>> && as = {} )
     356// Common implementation for the SUE instance types. Not to be used directly.
     357template<typename decl_t>
     358class SueInstType final : public ReferenceToType {
     359public:
     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 = {} )
    342365        : ReferenceToType( n, q, std::move(as) ), base() {}
    343         StructInstType( const StructDecl * b, CV::Qualifiers q = {},
    344                 std::vector<ptr<Attribute>> && as = {} );
     366
     367        SueInstType(
     368                const decl_t * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    345369
    346370        bool isComplete() const override;
    347371
    348         const StructDecl * aggr() const override { return base; }
    349 
    350         const Type * accept( Visitor & v ) const override { return v.visit( this ); }
    351 private:
    352         StructInstType * clone() const override { return new StructInstType{ *this }; }
    353         MUTATE_FRIEND
    354 };
    355 
    356 /// instance of union type
    357 class UnionInstType final : public ReferenceToType {
    358 public:
    359         readonly<UnionDecl> base;
    360 
    361         UnionInstType( const std::string& n, CV::Qualifiers q = {},
    362                 std::vector<ptr<Attribute>> && as = {} )
     372        const decl_t * aggr() const override { return base; }
     373
     374        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
     375private:
     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.
     381using StructInstType = SueInstType<StructDecl>;
     382
     383/// An instance of a union type.
     384using UnionInstType = SueInstType<UnionDecl>;
     385
     386/// An instance of an enum type.
     387using EnumInstType = SueInstType<EnumDecl>;
     388
     389/// An instance of a trait type.
     390class TraitInstType final : public ReferenceToType {
     391public:
     392        readonly<TraitDecl> base;
     393
     394        TraitInstType(
     395                const std::string& n, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
    363396        : 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 ); }
    372 private:
    373         UnionInstType * clone() const override { return new UnionInstType{ *this }; }
    374         MUTATE_FRIEND
    375 };
    376 
    377 /// instance of enum type
    378 class EnumInstType final : public ReferenceToType {
    379 public:
    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 ); }
    393 private:
    394         EnumInstType * clone() const override { return new EnumInstType{ *this }; }
    395         MUTATE_FRIEND
    396 };
    397 
    398 /// instance of trait type
    399 class TraitInstType final : public ReferenceToType {
    400 public:
    401         readonly<TraitDecl> base;
    402 
    403         TraitInstType( const std::string& n, CV::Qualifiers q = {},
    404                 std::vector<ptr<Attribute>> && as = {} )
    405         : ReferenceToType( n, q, std::move(as) ), base() {}
    406         TraitInstType( const TraitDecl * b, CV::Qualifiers q = {},
    407                 std::vector<ptr<Attribute>> && as = {} );
     397
     398        TraitInstType(
     399                const TraitDecl * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
    408400
    409401        // not meaningful for TraitInstType
     
    424416        TypeDecl::Kind kind;
    425417
    426         TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
     418        TypeInstType(
     419                const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
    427420                std::vector<ptr<Attribute>> && as = {} )
    428421        : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
     
    431424        : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
    432425
     426        TypeInstType( const TypeInstType & o );
     427
    433428        /// sets `base`, updating `kind` correctly
    434429        void set_base( const TypeDecl * );
  • src/AST/TypeEnvironment.cpp

    r309d814 r4c925cd  
    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.pass.result;
    164         }
    165 }
    166 
    167 bool TypeEnvironment::combine( 
     163                return occur.core.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

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

    r309d814 r4c925cd  
    1818
    1919namespace ast {
     20
     21
     22// size_t TypeSubstitution::Substituter::traceId = Stats::Heap::new_stacktrace_id("TypeSubstitution");
    2023
    2124TypeSubstitution::TypeSubstitution() {
     
    9295namespace {
    9396        struct EnvTrimmer {
    94                 ptr<TypeSubstitution> env;
     97                const TypeSubstitution * env;
    9598                TypeSubstitution * newEnv;
    9699                EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
     
    108111        if ( env ) {
    109112                TypeSubstitution * newEnv = new TypeSubstitution();
    110 #if TIME_TO_CONVERT_PASSES
    111113                Pass<EnvTrimmer> trimmer( env, newEnv );
    112114                expr->accept( trimmer );
    113 #else
    114                 (void)expr;
    115                 (void)env;
    116 #endif
    117115                return newEnv;
    118116        }
     
    121119
    122120void TypeSubstitution::normalize() {
    123 #if TIME_TO_CONVERT_PASSES
    124         PassVisitor<Substituter> sub( *this, true );
     121        Pass<Substituter> sub( *this, true );
    125122        do {
    126                 sub.pass.subCount = 0;
    127                 sub.pass.freeOnly = true;
     123                sub.core.subCount = 0;
     124                sub.core.freeOnly = true;
    128125                for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
    129                         i->second = i->second->acceptMutator( sub );
    130                 }
    131         } while ( sub.pass.subCount );
    132 #endif
    133 }
    134 
    135 #if TIME_TO_CONVERT_PASSES
    136 
    137 Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) {
     126                        i->second = i->second->accept( sub );
     127                }
     128        } while ( sub.core.subCount );
     129}
     130
     131const Type * TypeSubstitution::Substituter::postvisit( const TypeInstType *inst ) {
    138132        BoundVarsType::const_iterator bound = boundVars.find( inst->name );
    139133        if ( bound != boundVars.end() ) return inst;
     
    146140                // Note: this does not prevent cycles in the general case, so it may be necessary to do something more sophisticated here.
    147141                // TODO: investigate preventing type variables from being bound to themselves in the first place.
    148                 if ( TypeInstType * replacement = i->second.as<TypeInstType>() ) {
     142                if ( const TypeInstType * replacement = i->second.as<TypeInstType>() ) {
    149143                        if ( inst->name == replacement->name ) {
    150144                                return inst;
     
    153147                // std::cerr << "found " << inst->name << ", replacing with " << i->second << std::endl;
    154148                subCount++;
    155                 Type * newtype = i->second->clone();
    156                 newtype->get_qualifiers() |= inst->get_qualifiers();
    157                 delete inst;
    158                 // Note: need to recursively apply substitution to the new type because normalize does not substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
    159                 return newtype->acceptMutator( *visitor );
    160         } // if
    161 }
    162 
    163 Expression * TypeSubstitution::Substituter::postmutate( NameExpr * nameExpr ) {
     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
     158const Expr * TypeSubstitution::Substituter::postvisit( const NameExpr * nameExpr ) {
    164159        VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name );
    165160        if ( i == sub.varEnv.end() ) {
     
    167162        } else {
    168163                subCount++;
    169                 delete nameExpr;
    170                 return i->second->clone();
    171         } // if
    172 }
    173 
    174 void TypeSubstitution::Substituter::premutate( Type * type ) {
     164                return i->second;
     165        } // if
     166}
     167
     168void TypeSubstitution::Substituter::previsit( const ParameterizedType * ptype ) {
    175169        GuardValue( boundVars );
    176170        // bind type variables from forall-qualifiers
    177171        if ( freeOnly ) {
    178                 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
    179                         boundVars.insert( (*tyvar)->name );
     172                for ( const TypeDecl * tyvar : ptype->forall ) {
     173                                boundVars.insert( tyvar->name );
    180174                } // for
    181175        } // if
    182176}
    183177
    184 template< typename TypeClass >
    185 void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) {
     178void TypeSubstitution::Substituter::handleAggregateType( const ReferenceToType * type ) {
    186179        GuardValue( boundVars );
    187180        // bind type variables from forall-qualifiers
    188181        if ( freeOnly ) {
    189                 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
    190                         boundVars.insert( (*tyvar)->name );
     182                for ( const TypeDecl * tyvar : type->forall ) {
     183                        boundVars.insert( tyvar->name );
    191184                } // for
    192185                // bind type variables from generic type instantiations
    193                 std::list< TypeDecl* > *baseParameters = type->get_baseParameters();
    194                 if ( baseParameters && ! type->parameters.empty() ) {
    195                         for ( std::list< TypeDecl* >::const_iterator tyvar = baseParameters->begin(); tyvar != baseParameters->end(); ++tyvar ) {
    196                                 boundVars.insert( (*tyvar)->name );
    197                         } // for
    198                 } // if
    199         } // if
    200 }
    201 
    202 void TypeSubstitution::Substituter::premutate( StructInstType * aggregateUseType ) {
     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
     196void TypeSubstitution::Substituter::previsit( const StructInstType * aggregateUseType ) {
    203197        handleAggregateType( aggregateUseType );
    204198}
    205199
    206 void TypeSubstitution::Substituter::premutate( UnionInstType *aggregateUseType ) {
     200void TypeSubstitution::Substituter::previsit( const UnionInstType *aggregateUseType ) {
    207201        handleAggregateType( aggregateUseType );
    208202}
    209 
    210 #endif
    211203
    212204} // namespace ast
  • src/AST/TypeSubstitution.hpp

    r309d814 r4c925cd  
    4444        TypeSubstitution &operator=( const TypeSubstitution &other );
    4545
    46         template< typename SynTreeClass > int apply( const SynTreeClass *& input ) const;
    47         template< typename SynTreeClass > int applyFree( const SynTreeClass *& input ) const;
     46        template< typename SynTreeClass >
     47        struct ApplyResult {
     48                // const SynTreeClass * node;
     49                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;
    4855
    4956        template< typename node_t, enum Node::ref_type ref_t >
    5057        int apply( ptr_base< node_t, ref_t > & input ) const {
    5158                const node_t * p = input.get();
    52                 int ret = apply(p);
    53                 input = p;
    54                 return ret;
     59                auto ret = apply(p);
     60                input = ret.node;
     61                return ret.count;
    5562        }
    5663
     
    5865        int applyFree( ptr_base< node_t, ref_t > & input ) const {
    5966                const node_t * p = input.get();
    60                 int ret = applyFree(p);
    61                 input = p;
    62                 return ret;
     67                auto ret = applyFree(p);
     68                input = ret.node;
     69                return ret.count;
    6370        }
    6471
     
    9299        void initialize( const TypeSubstitution &src, TypeSubstitution &dest );
    93100
    94         template<typename pass_type>
     101        template<typename core_t>
    95102        friend class Pass;
    96103
     
    147154// PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals.
    148155#include "Pass.hpp"
     156#include "Copy.hpp"
    149157
    150158namespace ast {
     
    152160// definitition must happen after PassVisitor is included so that WithGuards can be used
    153161struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter> {
     162                static size_t traceId;
    154163
    155164                Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
    156165
    157 #if TIME_TO_CONVERT_PASSES
    158 
    159                 Type * postmutate( TypeInstType * aggregateUseType );
    160                 Expression * postmutate( NameExpr * nameExpr );
     166                const Type * postvisit( const TypeInstType * aggregateUseType );
     167                const Expr * postvisit( const NameExpr * nameExpr );
    161168
    162169                /// Records type variable bindings from forall-statements
    163                 void premutate( Type * type );
     170                void previsit( const ParameterizedType * type );
    164171                /// Records type variable bindings from forall-statements and instantiations of generic types
    165                 template< typename TypeClass > void handleAggregateType( TypeClass * type );
    166 
    167                 void premutate( StructInstType * aggregateUseType );
    168                 void premutate( UnionInstType * aggregateUseType );
    169 
    170 #endif
     172                void handleAggregateType( const ReferenceToType * type );
     173
     174                void previsit( const StructInstType * aggregateUseType );
     175                void previsit( const UnionInstType * aggregateUseType );
    171176
    172177                const TypeSubstitution & sub;
     
    179184
    180185template< typename SynTreeClass >
    181 int TypeSubstitution::apply( const SynTreeClass *& input ) const {
     186TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::apply( const SynTreeClass * input ) const {
    182187        assert( input );
    183188        Pass<Substituter> sub( *this, false );
    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;
     189        input = strict_dynamic_cast< const SynTreeClass * >( deepCopy(input)->accept( sub ) );
     190        return { input, sub.core.subCount };
    189191}
    190192
    191193template< typename SynTreeClass >
    192 int TypeSubstitution::applyFree( const SynTreeClass *& input ) const {
     194TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::applyFree( const SynTreeClass * input ) const {
    193195        assert( input );
    194196        Pass<Substituter> sub( *this, true );
    195197        input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
    196 ///     std::cerr << "substitution result is: ";
    197 ///     newType->print( std::cerr );
    198 ///     std::cerr << std::endl;
    199         return sub.pass.subCount;
     198        return { input, sub.core.subCount };
    200199}
    201200
  • src/AST/module.mk

    r309d814 r4c925cd  
    2222        AST/DeclReplacer.cpp \
    2323        AST/Expr.cpp \
     24        AST/ForallSubstitutionTable.cpp \
    2425        AST/GenericSubstitution.cpp \
    2526        AST/Init.cpp \
  • src/AST/porting.md

    r309d814 r4c925cd  
    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.
    4954
    5055All leaves of the `Node` inheritance tree are now declared `final`
  • src/Common/Eval.cc

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

    r309d814 r4c925cd  
    249249
    250250        /// Gets the note at the given scope
     251        Note& getNote() { return scopes.back().note; }
     252        const Note& getNote() const { return scopes.back().note; }
    251253        Note& getNote( size_type i ) { return scopes[i].note; }
    252254        const Note& getNote( size_type i ) const { return scopes[i].note; }
  • src/Common/Stats/Heap.cc

    r309d814 r4c925cd  
    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                }
    5579
    5680                void newPass( const char * const name ) {
     
    116140                        for(size_t i = 0; i < passes_cnt; i++) {
    117141                                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);
    118151                        }
    119152                        print('-', nct);
     
    188221                                                = std::max(passes[passes_cnt - 1].peak_allocs, passes[passes_cnt - 1].n_allocs);
    189222                                }
     223
     224                                if ( stacktrace_stats_enabled && stacktrace_depth > 0) {
     225                                        stacktrace_stats[trace[stacktrace_depth]].mallocs++;
     226                                }
    190227                                return __malloc( size );
    191228                        }
     
    196233                                        passes[passes_cnt - 1].frees++;
    197234                                        passes[passes_cnt - 1].n_allocs--;
     235                                }
     236                                if ( stacktrace_stats_enabled && stacktrace_depth > 0) {
     237                                        stacktrace_stats[trace[stacktrace_depth]].frees++;
    198238                                }
    199239                                return __free( ptr );
     
    208248                                                = std::max(passes[passes_cnt - 1].peak_allocs, passes[passes_cnt - 1].n_allocs);
    209249                                }
     250                                if ( stacktrace_stats_enabled && stacktrace_depth > 0) {
     251                                        stacktrace_stats[trace[stacktrace_depth]].mallocs++;
     252                                }
    210253                                return __calloc( nelem, size );
    211254                        }
     
    218261                                        passes[passes_cnt - 1].frees++;
    219262                                } // if
     263                                if ( stacktrace_stats_enabled && stacktrace_depth > 0) {
     264                                        stacktrace_stats[trace[stacktrace_depth]].mallocs++;
     265                                        stacktrace_stats[trace[stacktrace_depth]].frees++;
     266                                }
    220267                                return s;
    221268                        }
  • src/Common/Stats/Heap.h

    r309d814 r4c925cd  
    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();
    2226        }
    2327}
  • src/CompilationState.cc

    r309d814 r4c925cd  
    1414//
    1515
     16#include "config.h"
     17
    1618int
    1719        astp = false,
     
    2830        genproto = false,
    2931        deterministic_output = false,
     32        useNewAST = CFA_USE_NEW_AST,
    3033        nomainp = false,
    3134        parsep = false,
  • src/CompilationState.h

    r309d814 r4c925cd  
    2929        genproto,
    3030        deterministic_output,
     31        useNewAST,
    3132        nomainp,
    3233        parsep,
  • src/InitTweak/InitTweak.cc

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

    r309d814 r4c925cd  
    100100
    101101namespace {
    102         struct AdjustExprType_new final : public ast::WithShortCircuiting {
     102        class AdjustExprType_new final : public ast::WithShortCircuiting {
     103                const ast::SymbolTable & symtab;
     104        public:
    103105                const ast::TypeEnvironment & tenv;
    104                 const ast::SymbolTable & symtab;
    105106
    106107                AdjustExprType_new( const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
    107                 : tenv( e ), symtab( syms ) {}
     108                : symtab( syms ), tenv( e ) {}
    108109
    109                 void premutate( const ast::VoidType * ) { visit_children = false; }
    110                 void premutate( const ast::BasicType * ) { visit_children = false; }
    111                 void premutate( const ast::PointerType * ) { visit_children = false; }
    112                 void premutate( const ast::ArrayType * ) { visit_children = false; }
    113                 void premutate( const ast::FunctionType * ) { visit_children = false; }
    114                 void premutate( const ast::StructInstType * ) { visit_children = false; }
    115                 void premutate( const ast::UnionInstType * ) { visit_children = false; }
    116                 void premutate( const ast::EnumInstType * ) { visit_children = false; }
    117                 void premutate( const ast::TraitInstType * ) { visit_children = false; }
    118                 void premutate( const ast::TypeInstType * ) { visit_children = false; }
    119                 void premutate( const ast::TupleType * ) { visit_children = false; }
    120                 void premutate( const ast::VarArgsType * ) { visit_children = false; }
    121                 void premutate( const ast::ZeroType * ) { visit_children = false; }
    122                 void premutate( const ast::OneType * ) { visit_children = false; }
     110                void previsit( const ast::VoidType * ) { visit_children = false; }
     111                void previsit( const ast::BasicType * ) { visit_children = false; }
     112                void previsit( const ast::PointerType * ) { visit_children = false; }
     113                void previsit( const ast::ArrayType * ) { visit_children = false; }
     114                void previsit( const ast::FunctionType * ) { visit_children = false; }
     115                void previsit( const ast::StructInstType * ) { visit_children = false; }
     116                void previsit( const ast::UnionInstType * ) { visit_children = false; }
     117                void previsit( const ast::EnumInstType * ) { visit_children = false; }
     118                void previsit( const ast::TraitInstType * ) { visit_children = false; }
     119                void previsit( const ast::TypeInstType * ) { visit_children = false; }
     120                void previsit( const ast::TupleType * ) { visit_children = false; }
     121                void previsit( const ast::VarArgsType * ) { visit_children = false; }
     122                void previsit( const ast::ZeroType * ) { visit_children = false; }
     123                void previsit( const ast::OneType * ) { visit_children = false; }
    123124
    124                 const ast::Type * postmutate( const ast::ArrayType * at ) {
     125                const ast::Type * postvisit( const ast::ArrayType * at ) {
    125126                        return new ast::PointerType{ at->base, at->qualifiers };
    126127                }
    127128
    128                 const ast::Type * postmutate( const ast::FunctionType * ft ) {
     129                const ast::Type * postvisit( const ast::FunctionType * ft ) {
    129130                        return new ast::PointerType{ ft };
    130131                }
    131132
    132                 const ast::Type * postmutate( const ast::TypeInstType * inst ) {
     133                const ast::Type * postvisit( const ast::TypeInstType * inst ) {
    133134                        // replace known function-type-variables with pointer-to-function
    134135                        if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name ) ) {
  • src/ResolvExpr/Candidate.hpp

    r309d814 r4c925cd  
    5151
    5252        Candidate( const ast::Expr * x, const ast::TypeEnvironment & e )
    53         : expr( x ), cost( Cost::zero ), cvtCost( Cost::zero ), env( e ), open(), need() {}
     53        : expr( x ), cost( Cost::zero ), cvtCost( Cost::zero ), env( e ), open(), need() {
     54                assert(x->result);
     55        }
    5456
    5557        Candidate( const Candidate & o, const ast::Expr * x, const Cost & addedCost = Cost::zero )
    5658        : expr( x ), cost( o.cost + addedCost ), cvtCost( Cost::zero ), env( o.env ), open( o.open ),
    57           need( o.need ) {}
     59          need( o.need ) {
     60                assert(x->result);
     61        }
    5862
    5963        Candidate(
    60                 const ast::Expr * x, const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 
     64                const ast::Expr * x, const ast::TypeEnvironment & e, const ast::OpenVarSet & o,
    6165                const ast::AssertionSet & n, const Cost & c, const Cost & cvt = Cost::zero )
    62         : expr( x ), cost( c ), cvtCost( cvt ), env( e ), open( o ), need( n.begin(), n.end() ) {}
     66        : expr( x ), cost( c ), cvtCost( cvt ), env( e ), open( o ), need( n.begin(), n.end() ) {
     67                assert(x->result);
     68        }
    6369
    6470        Candidate(
     
    6672                ast::AssertionSet && n, const Cost & c, const Cost & cvt = Cost::zero )
    6773        : expr( x ), cost( c ), cvtCost( cvt ), env( std::move( e ) ), open( std::move( o ) ),
    68           need( n.begin(), n.end() ) {}
     74          need( n.begin(), n.end() ) {
     75                assert(x->result);
     76        }
    6977};
    7078
  • src/ResolvExpr/CandidateFinder.cpp

    r309d814 r4c925cd  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed Jun 5 14:30:00 2019
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Wed Jun 5 14:30:00 2019
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Oct  1 14:55:00 2019
     13// Update Count     : 2
    1414//
    1515
     
    5454                return new ast::CastExpr{ expr, expr->result->stripReferences() };
    5555        }
    56        
     56
    5757        return expr;
    5858}
     
    6161UniqueId globalResnSlot = 0;
    6262
    63 Cost computeConversionCost( 
    64         const ast::Type * argType, const ast::Type * paramType, const ast::SymbolTable & symtab,
    65         const ast::TypeEnvironment & env
     63Cost computeConversionCost(
     64        const ast::Type * argType, const ast::Type * paramType, bool argIsLvalue,
     65        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
    6666) {
    6767        PRINT(
     
    7474                std::cerr << std::endl;
    7575        )
    76         Cost convCost = conversionCost( argType, paramType, symtab, env );
     76        Cost convCost = conversionCost( argType, paramType, argIsLvalue, symtab, env );
    7777        PRINT(
    7878                std::cerr << std::endl << "cost is " << convCost << std::endl;
     
    107107
    108108        /// Computes conversion cost for a given expression to a given type
    109         const ast::Expr * computeExpressionConversionCost( 
    110                 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 
     109        const ast::Expr * computeExpressionConversionCost(
     110                const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost
    111111        ) {
    112                 Cost convCost = computeConversionCost( arg->result, paramType, symtab, env );
     112                Cost convCost = computeConversionCost(
     113                                arg->result, paramType, arg->get_lvalue(), symtab, env );
    113114                outCost += convCost;
    114115
    115                 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires 
    116                 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 
     116                // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires
     117                // conversion. Ignore poly cost for now, since this requires resolution of the cast to
    117118                // infer parameters and this does not currently work for the reason stated below
    118119                Cost tmpCost = convCost;
     
    123124                        return new ast::CastExpr{ arg, newType };
    124125
    125                         // xxx - *should* be able to resolve this cast, but at the moment pointers are not 
    126                         // castable to zero_t, but are implicitly convertible. This is clearly inconsistent, 
     126                        // xxx - *should* be able to resolve this cast, but at the moment pointers are not
     127                        // castable to zero_t, but are implicitly convertible. This is clearly inconsistent,
    127128                        // once this is fixed it should be possible to resolve the cast.
    128                         // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable, 
    129                         // but it shouldn't be because this makes the conversion from DT* to DT* since 
     129                        // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable,
     130                        // but it shouldn't be because this makes the conversion from DT* to DT* since
    130131                        // commontype(zero_t, DT*) is DT*, rather than nothing
    131132
    132133                        // CandidateFinder finder{ symtab, env };
    133134                        // finder.find( arg, ResolvMode::withAdjustment() );
    134                         // assertf( finder.candidates.size() > 0, 
     135                        // assertf( finder.candidates.size() > 0,
    135136                        //      "Somehow castable expression failed to find alternatives." );
    136                         // assertf( finder.candidates.size() == 1, 
     137                        // assertf( finder.candidates.size() == 1,
    137138                        //      "Somehow got multiple alternatives for known cast expression." );
    138139                        // return finder.candidates.front()->expr;
     
    143144
    144145        /// Computes conversion cost for a given candidate
    145         Cost computeApplicationConversionCost( 
    146                 CandidateRef cand, const ast::SymbolTable & symtab 
     146        Cost computeApplicationConversionCost(
     147                CandidateRef cand, const ast::SymbolTable & symtab
    147148        ) {
    148149                auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >();
     
    167168                                if ( function->isVarArgs ) {
    168169                                        convCost.incUnsafe();
    169                                         PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 
     170                                        PRINT( std::cerr << "end of params with varargs function: inc unsafe: "
    170171                                                << convCost << std::endl; ; )
    171172                                        // convert reference-typed expressions into value-typed expressions
    172                                         cand->expr = ast::mutate_field_index( 
    173                                                 appExpr, &ast::ApplicationExpr::args, i, 
     173                                        cand->expr = ast::mutate_field_index(
     174                                                appExpr, &ast::ApplicationExpr::args, i,
    174175                                                referenceToRvalueConversion( args[i], convCost ) );
    175176                                        continue;
     
    180181                                // Default arguments should be free - don't include conversion cost.
    181182                                // Unwrap them here because they are not relevant to the rest of the system
    182                                 cand->expr = ast::mutate_field_index( 
     183                                cand->expr = ast::mutate_field_index(
    183184                                        appExpr, &ast::ApplicationExpr::args, i, def->expr );
    184185                                ++param;
     
    188189                        // mark conversion cost and also specialization cost of param type
    189190                        const ast::Type * paramType = (*param)->get_type();
    190                         cand->expr = ast::mutate_field_index( 
    191                                 appExpr, &ast::ApplicationExpr::args, i, 
    192                                 computeExpressionConversionCost( 
     191                        cand->expr = ast::mutate_field_index(
     192                                appExpr, &ast::ApplicationExpr::args, i,
     193                                computeExpressionConversionCost(
    193194                                        args[i], paramType, symtab, cand->env, convCost ) );
    194195                        convCost.decSpec( specCost( paramType ) );
     
    198199                if ( param != params.end() ) return Cost::infinity;
    199200
    200                 // specialization cost of return types can't be accounted for directly, it disables 
     201                // specialization cost of return types can't be accounted for directly, it disables
    201202                // otherwise-identical calls, like this example based on auto-newline in the I/O lib:
    202203                //
     
    215216        }
    216217
    217         void makeUnifiableVars( 
    218                 const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars, 
    219                 ast::AssertionSet & need 
     218        void makeUnifiableVars(
     219                const ast::ParameterizedType * type, ast::OpenVarSet & unifiableVars,
     220                ast::AssertionSet & need
    220221        ) {
    221222                for ( const ast::TypeDecl * tyvar : type->forall ) {
     
    254255
    255256                ArgPack()
    256                 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 
     257                : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ),
    257258                  tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    258                
    259                 ArgPack( 
    260                         const ast::TypeEnvironment & env, const ast::AssertionSet & need, 
     259
     260                ArgPack(
     261                        const ast::TypeEnvironment & env, const ast::AssertionSet & need,
    261262                        const ast::AssertionSet & have, const ast::OpenVarSet & open )
    262                 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 
     263                : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ),
    263264                  open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    264                
     265
    265266                ArgPack(
    266                         std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env, 
    267                         ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open, 
    268                         unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero, 
     267                        std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env,
     268                        ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open,
     269                        unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero,
    269270                        unsigned nextExpl = 0, unsigned explAlt = 0 )
    270271                : parent(parent), expr( expr ), cost( cost ), env( move( env ) ), need( move( need ) ),
    271272                  have( move( have ) ), open( move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ),
    272273                  nextExpl( nextExpl ), explAlt( explAlt ) {}
    273                
     274
    274275                ArgPack(
    275                         const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 
     276                        const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need,
    276277                        ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added )
    277                 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ), 
    278                   need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ), 
     278                : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( move( env ) ),
     279                  need( move( need ) ), have( move( have ) ), open( move( open ) ), nextArg( nextArg ),
    279280                  tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {}
    280                
     281
    281282                /// true if this pack is in the middle of an exploded argument
    282283                bool hasExpl() const { return nextExpl > 0; }
     
    286287                        return args[ nextArg-1 ][ explAlt ];
    287288                }
    288                
     289
    289290                /// Ends a tuple expression, consolidating the appropriate args
    290291                void endTuple( const std::vector< ArgPack > & packs ) {
     
    307308
    308309        /// Instantiates an argument to match a parameter, returns false if no matching results left
    309         bool instantiateArgument( 
    310                 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args, 
    311                 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 
    312                 unsigned nTuples = 0 
     310        bool instantiateArgument(
     311                const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args,
     312                std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,
     313                unsigned nTuples = 0
    313314        ) {
    314315                if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) {
     
    318319                                // xxx - dropping initializer changes behaviour from previous, but seems correct
    319320                                // ^^^ need to handle the case where a tuple has a default argument
    320                                 if ( ! instantiateArgument( 
     321                                if ( ! instantiateArgument(
    321322                                        type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;
    322323                                nTuples = 0;
     
    329330                } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) {
    330331                        // paramType is a ttype, consumes all remaining arguments
    331                        
     332
    332333                        // completed tuples; will be spliced to end of results to finish
    333334                        std::vector< ArgPack > finalResults{};
     
    342343                                for ( std::size_t i = genStart; i < genEnd; ++i ) {
    343344                                        unsigned nextArg = results[i].nextArg;
    344                                        
     345
    345346                                        // use next element of exploded tuple if present
    346347                                        if ( results[i].hasExpl() ) {
     
    352353                                                results.emplace_back(
    353354                                                        i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),
    354                                                         copy( results[i].need ), copy( results[i].have ), 
     355                                                        copy( results[i].need ), copy( results[i].have ),
    355356                                                        copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl,
    356357                                                        results[i].explAlt );
     
    370371                                                        // push empty tuple expression
    371372                                                        newResult.parent = i;
    372                                                         std::vector< ast::ptr< ast::Expr > > emptyList;
    373                                                         newResult.expr =
    374                                                                 new ast::TupleExpr{ CodeLocation{}, move( emptyList ) };
     373                                                        newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} };
    375374                                                        argType = newResult.expr->result;
    376375                                                } else {
     
    400399
    401400                                                // check unification for ttype before adding to final
    402                                                 if ( 
    403                                                         unify( 
     401                                                if (
     402                                                        unify(
    404403                                                                ttype, argType, newResult.env, newResult.need, newResult.have,
    405                                                                 newResult.open, symtab ) 
     404                                                                newResult.open, symtab )
    406405                                                ) {
    407406                                                        finalResults.emplace_back( move( newResult ) );
     
    424423                                                if ( expl.exprs.empty() ) {
    425424                                                        results.emplace_back(
    426                                                                 results[i], move( env ), copy( results[i].need ), 
     425                                                                results[i], move( env ), copy( results[i].need ),
    427426                                                                copy( results[i].have ), move( open ), nextArg + 1, expl.cost );
    428                                                        
     427
    429428                                                        continue;
    430429                                                }
     
    432431                                                // add new result
    433432                                                results.emplace_back(
    434                                                         i, expl.exprs.front(), move( env ), copy( results[i].need ), 
    435                                                         copy( results[i].have ), move( open ), nextArg + 1, nTuples, 
     433                                                        i, expl.exprs.front(), move( env ), copy( results[i].need ),
     434                                                        copy( results[i].have ), move( open ), nextArg + 1, nTuples,
    436435                                                        expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    437436                                        }
     
    479478
    480479                                        results.emplace_back(
    481                                                 i, expr, move( env ), move( need ), move( have ), move( open ), nextArg, 
     480                                                i, expr, move( env ), move( need ), move( have ), move( open ), nextArg,
    482481                                                nTuples, Cost::zero, nextExpl, results[i].explAlt );
    483482                                }
     
    495494                                        if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {
    496495                                                results.emplace_back(
    497                                                         i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ), 
     496                                                        i, new ast::DefaultArgExpr{ cnst->location, cnst }, move( env ),
    498497                                                        move( need ), move( have ), move( open ), nextArg, nTuples );
    499498                                        }
     
    517516                                if ( expl.exprs.empty() ) {
    518517                                        results.emplace_back(
    519                                                 results[i], move( env ), move( need ), move( have ), move( open ), 
     518                                                results[i], move( env ), move( need ), move( have ), move( open ),
    520519                                                nextArg + 1, expl.cost );
    521                                        
     520
    522521                                        continue;
    523522                                }
     
    539538                                        // add new result
    540539                                        results.emplace_back(
    541                                                 i, expr, move( env ), move( need ), move( have ), move( open ), 
     540                                                i, expr, move( env ), move( need ), move( have ), move( open ),
    542541                                                nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    543542                                }
     
    548547                genStart = genEnd;
    549548
    550                 return genEnd != results.size();
     549                return genEnd != results.size();  // were any new results added?
    551550        }
    552551
    553552        /// Generate a cast expression from `arg` to `toType`
    554         const ast::Expr * restructureCast( 
     553        const ast::Expr * restructureCast(
    555554                ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast
    556555        ) {
    557                 if ( 
    558                         arg->result->size() > 1 
    559                         && ! toType->isVoid() 
    560                         && ! dynamic_cast< const ast::ReferenceType * >( toType ) 
     556                if (
     557                        arg->result->size() > 1
     558                        && ! toType->isVoid()
     559                        && ! dynamic_cast< const ast::ReferenceType * >( toType )
    561560                ) {
    562                         // Argument is a tuple and the target type is neither void nor a reference. Cast each 
    563                         // member of the tuple to its corresponding target type, producing the tuple of those 
    564                         // cast expressions. If there are more components of the tuple than components in the 
    565                         // target type, then excess components do not come out in the result expression (but 
     561                        // Argument is a tuple and the target type is neither void nor a reference. Cast each
     562                        // member of the tuple to its corresponding target type, producing the tuple of those
     563                        // cast expressions. If there are more components of the tuple than components in the
     564                        // target type, then excess components do not come out in the result expression (but
    566565                        // UniqueExpr ensures that the side effects will still be produced)
    567566                        if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {
    568                                 // expressions which may contain side effects require a single unique instance of 
     567                                // expressions which may contain side effects require a single unique instance of
    569568                                // the expression
    570569                                arg = new ast::UniqueExpr{ arg->location, arg };
     
    574573                                // cast each component
    575574                                ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i };
    576                                 components.emplace_back( 
     575                                components.emplace_back(
    577576                                        restructureCast( idx, toType->getComponent( i ), isGenerated ) );
    578577                        }
     
    594593
    595594        /// Actually visits expressions to find their candidate interpretations
    596         struct Finder final : public ast::WithShortCircuiting {
     595        class Finder final : public ast::WithShortCircuiting {
     596                const ast::SymbolTable & symtab;
     597        public:
     598                static size_t traceId;
    597599                CandidateFinder & selfFinder;
    598                 const ast::SymbolTable & symtab;
    599600                CandidateList & candidates;
    600601                const ast::TypeEnvironment & tenv;
    601602                ast::ptr< ast::Type > & targetType;
    602603
     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
    603618                Finder( CandidateFinder & f )
    604                 : selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ),
     619                : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
    605620                  targetType( f.targetType ) {}
    606                
     621
    607622                void previsit( const ast::Node * ) { visit_children = false; }
    608623
     
    611626                void addCandidate( Args &&... args ) {
    612627                        candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } );
     628                        reason.code = NoReason;
    613629                }
    614630
     
    639655
    640656                /// Completes a function candidate with arguments located
    641                 void validateFunctionCandidate( 
    642                         const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 
    643                         CandidateList & out 
     657                void validateFunctionCandidate(
     658                        const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,
     659                        CandidateList & out
    644660                ) {
    645                         ast::ApplicationExpr * appExpr = 
     661                        ast::ApplicationExpr * appExpr =
    646662                                new ast::ApplicationExpr{ func->expr->location, func->expr };
    647663                        // sum cost and accumulate arguments
     
    657673                        appExpr->args = move( vargs );
    658674                        // build and validate new candidate
    659                         auto newCand = 
     675                        auto newCand =
    660676                                std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );
    661677                        PRINT(
     
    669685                /// Builds a list of candidates for a function, storing them in out
    670686                void makeFunctionCandidates(
    671                         const CandidateRef & func, const ast::FunctionType * funcType, 
     687                        const CandidateRef & func, const ast::FunctionType * funcType,
    672688                        const ExplodedArgs_new & args, CandidateList & out
    673689                ) {
     
    676692                        ast::TypeEnvironment funcEnv{ func->env };
    677693                        makeUnifiableVars( funcType, funcOpen, funcNeed );
    678                         // add all type variables as open variables now so that those not used in the parameter
    679                         // list are still considered open
     694                        // add all type variables as open variables now so that those not used in the
     695                        // parameter list are still considered open
    680696                        funcEnv.add( funcType->forall );
    681697
     
    683699                                // attempt to narrow based on expected target type
    684700                                const ast::Type * returnType = funcType->returns.front()->get_type();
    685                                 if ( ! unify( 
    686                                         returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 
     701                                if ( ! unify(
     702                                        returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
    687703                                ) {
    688704                                        // unification failed, do not pursue this candidate
     
    698714                        for ( const ast::DeclWithType * param : funcType->params ) {
    699715                                auto obj = strict_dynamic_cast< const ast::ObjectDecl * >( param );
    700                                 // Try adding the arguments corresponding to the current parameter to the existing 
     716                                // Try adding the arguments corresponding to the current parameter to the existing
    701717                                // matches
    702                                 if ( ! instantiateArgument( 
     718                                if ( ! instantiateArgument(
    703719                                        obj->type, obj->init, args, results, genStart, symtab ) ) return;
    704720                        }
     
    750766                                                        if ( expl.exprs.empty() ) {
    751767                                                                results.emplace_back(
    752                                                                         results[i], move( env ), copy( results[i].need ), 
    753                                                                         copy( results[i].have ), move( open ), nextArg + 1, 
     768                                                                        results[i], move( env ), copy( results[i].need ),
     769                                                                        copy( results[i].have ), move( open ), nextArg + 1,
    754770                                                                        expl.cost );
    755771
     
    760776                                                        results.emplace_back(
    761777                                                                i, expl.exprs.front(), move( env ), copy( results[i].need ),
    762                                                                 copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost, 
     778                                                                copy( results[i].have ), move( open ), nextArg + 1, 0, expl.cost,
    763779                                                                expl.exprs.size() == 1 ? 0 : 1, j );
    764780                                                }
     
    780796                /// Adds implicit struct-conversions to the alternative list
    781797                void addAnonConversions( const CandidateRef & cand ) {
    782                         // adds anonymous member interpretations whenever an aggregate value type is seen. 
    783                         // it's okay for the aggregate expression to have reference type -- cast it to the 
     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
    784800                        // base type to treat the aggregate as the referenced value
    785801                        ast::ptr< ast::Expr > aggrExpr( cand->expr );
    786802                        ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;
    787803                        cand->env.apply( aggrType );
    788                        
     804
    789805                        if ( aggrType.as< ast::ReferenceType >() ) {
    790806                                aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };
     
    799815
    800816                /// Adds aggregate member interpretations
    801                 void addAggMembers( 
    802                         const ast::ReferenceToType * aggrInst, const ast::Expr * expr, 
    803                         const Candidate & cand, const Cost & addedCost, const std::string & name 
     817                void addAggMembers(
     818                        const ast::ReferenceToType * aggrInst, const ast::Expr * expr,
     819                        const Candidate & cand, const Cost & addedCost, const std::string & name
    804820                ) {
    805821                        for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {
    806822                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );
    807                                 CandidateRef newCand = std::make_shared<Candidate>( 
     823                                CandidateRef newCand = std::make_shared<Candidate>(
    808824                                        cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
    809                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     825                                // add anonymous member interpretations whenever an aggregate value type is seen
    810826                                // as a member expression
    811827                                addAnonConversions( newCand );
     
    815831
    816832                /// Adds tuple member interpretations
    817                 void addTupleMembers( 
    818                         const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 
    819                         const Cost & addedCost, const ast::Expr * member 
     833                void addTupleMembers(
     834                        const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,
     835                        const Cost & addedCost, const ast::Expr * member
    820836                ) {
    821837                        if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) {
    822                                 // get the value of the constant expression as an int, must be between 0 and the 
     838                                // get the value of the constant expression as an int, must be between 0 and the
    823839                                // length of the tuple to have meaning
    824840                                long long val = constantExpr->intValue();
    825841                                if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    826842                                        addCandidate(
    827                                                 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 
     843                                                cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },
    828844                                                addedCost );
    829845                                }
     
    837853                        if ( funcFinder.candidates.empty() ) return;
    838854
    839                         std::vector< CandidateFinder > argCandidates =
     855                        reason.code = NoMatch;
     856
     857                        std::vector< CandidateFinder > argCandidates =
    840858                                selfFinder.findSubExprs( untypedExpr->args );
    841                        
     859
    842860                        // take care of possible tuple assignments
    843861                        // if not tuple assignment, handled as normal function call
     
    877895                                                if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    878896                                                        CandidateRef newFunc{ new Candidate{ *func } };
    879                                                         newFunc->expr = 
     897                                                        newFunc->expr =
    880898                                                                referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    881899                                                        makeFunctionCandidates( newFunc, function, argExpansions, found );
    882900                                                }
    883                                         } else if ( 
    884                                                 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 
     901                                        } else if (
     902                                                auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
    885903                                        ) {
    886904                                                if ( const ast::EqvClass * clz = func->env.lookup( inst->name ) ) {
    887905                                                        if ( auto function = clz->bound.as< ast::FunctionType >() ) {
    888906                                                                CandidateRef newFunc{ new Candidate{ *func } };
    889                                                                 newFunc->expr = 
     907                                                                newFunc->expr =
    890908                                                                        referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    891909                                                                makeFunctionCandidates( newFunc, function, argExpansions, found );
     
    901919                                std::vector< ExplodedArg > funcE;
    902920                                funcE.reserve( funcFinder.candidates.size() );
    903                                 for ( const CandidateRef & func : funcFinder ) { 
     921                                for ( const CandidateRef & func : funcFinder ) {
    904922                                        funcE.emplace_back( *func, symtab );
    905923                                }
     
    913931                                                        if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    914932                                                                CandidateRef newOp{ new Candidate{ *op} };
    915                                                                 newOp->expr = 
     933                                                                newOp->expr =
    916934                                                                        referenceToRvalueConversion( newOp->expr, newOp->cost );
    917935                                                                makeFunctionCandidates( newOp, function, argExpansions, found );
     
    922940                        }
    923941
    924                         // Implement SFINAE; resolution errors are only errors if there aren't any non-error 
     942                        // Implement SFINAE; resolution errors are only errors if there aren't any non-error
    925943                        // candidates
    926944                        if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
     
    934952                                        auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
    935953                                        auto function = pointer->base.strict_as< ast::FunctionType >();
    936                                        
     954
    937955                                        std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;
    938956                                        std::cerr << "parameters are:" << std::endl;
     
    957975                        promoteCvtCost( winners );
    958976
    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 
     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
    961979                        // `findMinCost`, since anon conversions are never the cheapest
    962980                        for ( const CandidateRef & c : winners ) {
     
    966984
    967985                        if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
    968                                 // If resolution is unsuccessful with a target type, try again without, since it 
     986                                // If resolution is unsuccessful with a target type, try again without, since it
    969987                                // will sometimes succeed when it wouldn't with a target type binding.
    970988                                // For example:
     
    9831001                /// true if expression is an lvalue
    9841002                static bool isLvalue( const ast::Expr * x ) {
    985                         return x->result && ( x->result->is_lvalue() || x->result.as< ast::ReferenceType >() );
     1003                        return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() );
    9861004                }
    9871005
     
    9891007                        CandidateFinder finder{ symtab, tenv };
    9901008                        finder.find( addressExpr->arg );
     1009
     1010                        if( finder.candidates.empty() ) return;
     1011
     1012                        reason.code = NoMatch;
     1013
    9911014                        for ( CandidateRef & r : finder.candidates ) {
    9921015                                if ( ! isLvalue( r->expr ) ) continue;
     
    10091032                        finder.find( castExpr->arg, ResolvMode::withAdjustment() );
    10101033
     1034                        if( !finder.candidates.empty() ) reason.code = NoMatch;
     1035
    10111036                        CandidateList matches;
    10121037                        for ( CandidateRef & cand : finder.candidates ) {
     
    10161041                                cand->env.extractOpenVars( open );
    10171042
    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 
     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
    10211046                                // has fewer results than there are types to cast to.
    10221047                                int discardedValues = cand->expr->result->size() - toType->size();
     
    10251050                                // unification run for side-effects
    10261051                                unify( toType, cand->expr->result, cand->env, need, have, open, symtab );
    1027                                 Cost thisCost = castCost( cand->expr->result, toType, symtab, cand->env );
     1052                                Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1053                                                symtab, cand->env );
    10281054                                PRINT(
    10291055                                        std::cerr << "working on cast with result: " << toType << std::endl;
     
    10371063                                        // count one safe conversion for each value that is thrown away
    10381064                                        thisCost.incSafe( discardedValues );
    1039                                         CandidateRef newCand = std::make_shared<Candidate>( 
    1040                                                 restructureCast( cand->expr, toType, castExpr->isGenerated ), 
    1041                                                 copy( cand->env ), move( open ), move( need ), cand->cost, 
     1065                                        CandidateRef newCand = std::make_shared<Candidate>(
     1066                                                restructureCast( cand->expr, toType, castExpr->isGenerated ),
     1067                                                copy( cand->env ), move( open ), move( need ), cand->cost,
    10421068                                                cand->cost + thisCost );
    10431069                                        inferParameters( newCand, matches );
     
    10571083                        finder.find( castExpr->arg, ResolvMode::withoutPrune() );
    10581084                        for ( CandidateRef & r : finder.candidates ) {
    1059                                 addCandidate( 
    1060                                         *r, 
     1085                                addCandidate(
     1086                                        *r,
    10611087                                        new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
    10621088                        }
     
    10671093                        aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    10681094                        for ( CandidateRef & agg : aggFinder.candidates ) {
    1069                                 // it's okay for the aggregate expression to have reference type -- cast it to the 
     1095                                // it's okay for the aggregate expression to have reference type -- cast it to the
    10701096                                // base type to treat the aggregate as the referenced value
    10711097                                Cost addedCost = Cost::zero;
     
    10741100                                // find member of the given type
    10751101                                if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {
    1076                                         addAggMembers( 
     1102                                        addAggMembers(
    10771103                                                structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10781104                                } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {
    1079                                         addAggMembers( 
     1105                                        addAggMembers(
    10801106                                                unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    10811107                                } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {
     
    10921118                        std::vector< ast::SymbolTable::IdData > declList = symtab.lookupId( nameExpr->name );
    10931119                        PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
     1120                        if( declList.empty() ) return;
     1121
     1122                        reason.code = NoMatch;
     1123
    10941124                        for ( auto & data : declList ) {
    10951125                                Cost cost = Cost::zero;
     
    10971127
    10981128                                CandidateRef newCand = std::make_shared<Candidate>(
    1099                                         newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 
     1129                                        newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
    11001130                                        cost );
    11011131                                PRINT(
     
    11071137                                        std::cerr << std::endl;
    11081138                                )
    1109                                 newCand->expr = ast::mutate_field( 
    1110                                         newCand->expr.get(), &ast::Expr::result, 
     1139                                newCand->expr = ast::mutate_field(
     1140                                        newCand->expr.get(), &ast::Expr::result,
    11111141                                        renameTyVars( newCand->expr->result ) );
    1112                                 // add anonymous member interpretations whenever an aggregate value type is seen 
     1142                                // add anonymous member interpretations whenever an aggregate value type is seen
    11131143                                // as a name expression
    11141144                                addAnonConversions( newCand );
     
    11201150                        // not sufficient to just pass `variableExpr` here, type might have changed since
    11211151                        // creation
    1122                         addCandidate( 
     1152                        addCandidate(
    11231153                                new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
    11241154                }
     
    11301160                void postvisit( const ast::SizeofExpr * sizeofExpr ) {
    11311161                        if ( sizeofExpr->type ) {
    1132                                 addCandidate( 
    1133                                         new ast::SizeofExpr{ 
    1134                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) }, 
     1162                                addCandidate(
     1163                                        new ast::SizeofExpr{
     1164                                                sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
    11351165                                        tenv );
    11361166                        } else {
     
    11411171                                CandidateList winners = findMinCost( finder.candidates );
    11421172                                if ( winners.size() != 1 ) {
    1143                                         SemanticError( 
     1173                                        SemanticError(
    11441174                                                sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );
    11451175                                }
     
    11541184                void postvisit( const ast::AlignofExpr * alignofExpr ) {
    11551185                        if ( alignofExpr->type ) {
    1156                                 addCandidate( 
    1157                                         new ast::AlignofExpr{ 
    1158                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) }, 
     1186                                addCandidate(
     1187                                        new ast::AlignofExpr{
     1188                                                alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
    11591189                                        tenv );
    11601190                        } else {
     
    11651195                                CandidateList winners = findMinCost( finder.candidates );
    11661196                                if ( winners.size() != 1 ) {
    1167                                         SemanticError( 
     1197                                        SemanticError(
    11681198                                                alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );
    11691199                                }
     
    11721202                                choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    11731203                                choice->cost = Cost::zero;
    1174                                 addCandidate( 
     1204                                addCandidate(
    11751205                                        *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );
    11761206                        }
     
    11851215                        for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {
    11861216                                auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );
    1187                                 addCandidate( 
     1217                                addCandidate(
    11881218                                        new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );
    11891219                        }
     
    12061236                        finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );
    12071237                        if ( finder2.candidates.empty() ) return;
     1238
     1239                        reason.code = NoMatch;
    12081240
    12091241                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    12181250
    12191251                                        addCandidate(
    1220                                                 new ast::LogicalExpr{ 
     1252                                                new ast::LogicalExpr{
    12211253                                                        logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
    12221254                                                move( env ), move( open ), move( need ), r1->cost + r2->cost );
     
    12401272                        finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );
    12411273                        if ( finder3.candidates.empty() ) return;
     1274
     1275                        reason.code = NoMatch;
    12421276
    12431277                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    12561290                                                ast::AssertionSet have;
    12571291
    1258                                                 // unify true and false results, then infer parameters to produce new 
     1292                                                // unify true and false results, then infer parameters to produce new
    12591293                                                // candidates
    12601294                                                ast::ptr< ast::Type > common;
    1261                                                 if ( 
    1262                                                         unify( 
    1263                                                                 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 
    1264                                                                 common ) 
     1295                                                if (
     1296                                                        unify(
     1297                                                                r2->expr->result, r3->expr->result, env, need, have, open, symtab,
     1298                                                                common )
    12651299                                                ) {
    12661300                                                        // generate typed expression
    1267                                                         ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 
     1301                                                        ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{
    12681302                                                                conditionalExpr->location, r1->expr, r2->expr, r3->expr };
    12691303                                                        newExpr->result = common ? common : r2->expr->result;
    12701304                                                        // convert both options to result type
    12711305                                                        Cost cost = r1->cost + r2->cost + r3->cost;
    1272                                                         newExpr->arg2 = computeExpressionConversionCost( 
     1306                                                        newExpr->arg2 = computeExpressionConversionCost(
    12731307                                                                newExpr->arg2, newExpr->result, symtab, env, cost );
    12741308                                                        newExpr->arg3 = computeExpressionConversionCost(
     
    12871321                        ast::TypeEnvironment env{ tenv };
    12881322                        ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
    1289                        
     1323
    12901324                        CandidateFinder finder2{ symtab, env };
    12911325                        finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
     
    13171351                        finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );
    13181352                        if ( finder2.candidates.empty() ) return;
     1353
     1354                        reason.code = NoMatch;
    13191355
    13201356                        for ( const CandidateRef & r1 : finder1.candidates ) {
     
    13301366
    13311367                                        ast::ptr< ast::Type > common;
    1332                                         if ( 
    1333                                                 unify( 
    1334                                                         r1->expr->result, r2->expr->result, env, need, have, open, symtab, 
    1335                                                         common ) 
     1368                                        if (
     1369                                                unify(
     1370                                                        r1->expr->result, r2->expr->result, env, need, have, open, symtab,
     1371                                                        common )
    13361372                                        ) {
    13371373                                                // generate new expression
    1338                                                 ast::RangeExpr * newExpr = 
     1374                                                ast::RangeExpr * newExpr =
    13391375                                                        new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
    13401376                                                newExpr->result = common ? common : r1->expr->result;
    13411377                                                // add candidate
    13421378                                                CandidateRef newCand = std::make_shared<Candidate>(
    1343                                                         newExpr, move( env ), move( open ), move( need ), 
     1379                                                        newExpr, move( env ), move( open ), move( need ),
    13441380                                                        r1->cost + r2->cost );
    13451381                                                inferParameters( newCand, candidates );
     
    13501386
    13511387                void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
    1352                         std::vector< CandidateFinder > subCandidates = 
     1388                        std::vector< CandidateFinder > subCandidates =
    13531389                                selfFinder.findSubExprs( tupleExpr->exprs );
    13541390                        std::vector< CandidateList > possibilities;
     
    13701406
    13711407                                addCandidate(
    1372                                         new ast::TupleExpr{ tupleExpr->location, move( exprs ) }, 
     1408                                        new ast::TupleExpr{ tupleExpr->location, move( exprs ) },
    13731409                                        move( env ), move( open ), move( need ), sumCost( subs ) );
    13741410                        }
     
    14121448                                toType = SymTab::validateType( initExpr->location, toType, symtab );
    14131449                                toType = adjustExprType( toType, tenv, symtab );
    1414                                 // The call to find must occur inside this loop, otherwise polymorphic return 
    1415                                 // types are not bound to the initialization type, since return type variables are 
    1416                                 // only open for the duration of resolving the UntypedExpr. 
     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.
    14171453                                CandidateFinder finder{ symtab, tenv, toType };
    14181454                                finder.find( initExpr->expr, ResolvMode::withAdjustment() );
    14191455                                for ( CandidateRef & cand : finder.candidates ) {
     1456                                        if(reason.code == NotFound) reason.code = NoMatch;
     1457
    14201458                                        ast::TypeEnvironment env{ cand->env };
    14211459                                        ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;
     
    14261464                                        )
    14271465
    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 
     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
    14311469                                        // if it has fewer results than there are types to cast to.
    14321470                                        int discardedValues = cand->expr->result->size() - toType->size();
     
    14351473                                        // unification run for side-effects
    14361474                                        unify( toType, cand->expr->result, env, need, have, open, symtab );
    1437                                         Cost thisCost = castCost( cand->expr->result, toType, symtab, env );
    1438                                        
     1475                                        Cost thisCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1476                                                        symtab, env );
     1477
    14391478                                        if ( thisCost != Cost::infinity ) {
    14401479                                                // count one safe conversion for each value that is thrown away
    14411480                                                thisCost.incSafe( discardedValues );
    1442                                                 CandidateRef newCand = std::make_shared<Candidate>( 
    1443                                                         new ast::InitExpr{ 
    1444                                                                 initExpr->location, restructureCast( cand->expr, toType ), 
    1445                                                                 initAlt.designation }, 
     1481                                                CandidateRef newCand = std::make_shared<Candidate>(
     1482                                                        new ast::InitExpr{
     1483                                                                initExpr->location, restructureCast( cand->expr, toType ),
     1484                                                                initAlt.designation },
    14461485                                                        copy( cand->env ), move( open ), move( need ), cand->cost, thisCost );
    14471486                                                inferParameters( newCand, matches );
     
    14691508        };
    14701509
    1471         /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
     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
    14721512        /// return type. Skips ambiguous candidates.
    14731513        CandidateList pruneCandidates( CandidateList & candidates ) {
     
    14861526                        {
    14871527                                ast::ptr< ast::Type > newType = candidate->expr->result;
     1528                                assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());
    14881529                                candidate->env.apply( newType );
    14891530                                mangleName = Mangle::mangle( newType );
     
    14941535                                if ( candidate->cost < found->second.candidate->cost ) {
    14951536                                        PRINT(
    1496                                                 std::cerr << "cost " << candidate->cost << " beats " 
     1537                                                std::cerr << "cost " << candidate->cost << " beats "
    14971538                                                        << found->second.candidate->cost << std::endl;
    14981539                                        )
     
    15001541                                        found->second = PruneStruct{ candidate };
    15011542                                } else if ( candidate->cost == found->second.candidate->cost ) {
    1502                                         // if one of the candidates contains a deleted identifier, can pick the other, 
    1503                                         // since deleted expressions should not be ambiguous if there is another option 
     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
    15041545                                        // that is at least as good
    15051546                                        if ( findDeletedExpr( candidate->expr ) ) {
     
    15151556                                } else {
    15161557                                        PRINT(
    1517                                                 std::cerr << "cost " << candidate->cost << " loses to " 
     1558                                                std::cerr << "cost " << candidate->cost << " loses to "
    15181559                                                        << found->second.candidate->cost << std::endl;
    15191560                                        )
     
    15301571
    15311572                        CandidateRef cand = target.second.candidate;
    1532                        
     1573
    15331574                        ast::ptr< ast::Type > newResult = cand->expr->result;
    15341575                        cand->env.applyFree( newResult );
    15351576                        cand->expr = ast::mutate_field(
    15361577                                cand->expr.get(), &ast::Expr::result, move( newResult ) );
    1537                        
     1578
    15381579                        out.emplace_back( cand );
    15391580                }
     
    15491590
    15501591        if ( mode.failFast && candidates.empty() ) {
    1551                 SemanticError( expr, "No reasonable alternatives for expression " );
     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                }
    15521605        }
    15531606
     
    15581611                std::vector< std::string > errors;
    15591612                for ( CandidateRef & candidate : candidates ) {
    1560                         satisfyAssertions( candidate, symtab, satisfied, errors );
     1613                        satisfyAssertions( candidate, localSyms, satisfied, errors );
    15611614                }
    15621615
     
    15831636
    15841637                CandidateList pruned = pruneCandidates( candidates );
    1585                
     1638
    15861639                if ( mode.failFast && pruned.empty() ) {
    15871640                        std::ostringstream stream;
     
    16021655                )
    16031656                PRINT(
    1604                         std::cerr << "there are " << candidates.size() << " alternatives after elimination" 
     1657                        std::cerr << "there are " << candidates.size() << " alternatives after elimination"
    16051658                                << std::endl;
    16061659                )
    16071660        }
    16081661
    1609         // adjust types after pruning so that types substituted by pruneAlternatives are correctly 
     1662        // adjust types after pruning so that types substituted by pruneAlternatives are correctly
    16101663        // adjusted
    16111664        if ( mode.adjust ) {
    16121665                for ( CandidateRef & r : candidates ) {
    1613                         r->expr = ast::mutate_field( 
    1614                                 r->expr.get(), &ast::Expr::result, 
    1615                                 adjustExprType( r->expr->result, r->env, symtab ) );
     1666                        r->expr = ast::mutate_field(
     1667                                r->expr.get(), &ast::Expr::result,
     1668                                adjustExprType( r->expr->result, r->env, localSyms ) );
    16161669                }
    16171670        }
     
    16251678}
    16261679
    1627 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 
    1628         const std::vector< ast::ptr< ast::Expr > > & xs 
     1680std::vector< CandidateFinder > CandidateFinder::findSubExprs(
     1681        const std::vector< ast::ptr< ast::Expr > > & xs
    16291682) {
    16301683        std::vector< CandidateFinder > out;
    16311684
    16321685        for ( const auto & x : xs ) {
    1633                 out.emplace_back( symtab, env );
     1686                out.emplace_back( localSyms, env );
    16341687                out.back().find( x, ResolvMode::withAdjustment() );
    1635                
     1688
    16361689                PRINT(
    16371690                        std::cerr << "findSubExprs" << std::endl;
  • src/ResolvExpr/CandidateFinder.hpp

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

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

    r309d814 r4c925cd  
    666666                const ast::OpenVarSet & open;
    667667        public:
     668                static size_t traceId;
    668669                ast::ptr< ast::Type > result;
    669670
     
    893894        };
    894895
     896        // size_t CommonType_new::traceId = Stats::Heap::new_stacktrace_id("CommonType_new");
    895897        namespace {
    896898                ast::ptr< ast::Type > handleReference(
     
    939941                        ast::ptr< ast::Type > result;
    940942                        const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >();
    941                         const ast::ReferenceType * ref2 = type1.as< ast::ReferenceType >();
     943                        const ast::ReferenceType * ref2 = type2.as< ast::ReferenceType >();
    942944
    943945                        if ( depth1 > depth2 ) {
     
    966968                ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open };
    967969                type1->accept( visitor );
    968                 ast::ptr< ast::Type > result = visitor.pass.result;
     970                ast::ptr< ast::Type > result = visitor.core.result;
    969971
    970972                // handling for opaque type declarations (?)
  • src/ResolvExpr/ConversionCost.cc

    r309d814 r4c925cd  
    481481        }
    482482
    483 static 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.
    490 static 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 ); }
     483namespace {
     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}
    494494
    495495Cost conversionCost(
    496         const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    497         const ast::TypeEnvironment & env
     496        const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
     497        const ast::SymbolTable & symtab, 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, symtab, env );
     502                                return conversionCost(src, eqv->bound, srcIsLvalue, symtab, env );
    503503                        } else {
    504504                                return Cost::infinity;
     
    508508                        assertf( type, "Unexpected typedef." );
    509509                        if ( type->base ) {
    510                                 return conversionCost( src, type->base, symtab, env ) + Cost::safe;
     510                                return conversionCost( src, type->base, srcIsLvalue, 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, symtab, env, localPtrsAssignable );
     520                return convertToReferenceCost( src, refType, srcIsLvalue, symtab, env, localPtrsAssignable );
    521521        } else {
    522                 ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
     522                ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
    523523                src->accept( converter );
    524                 return converter.pass.cost;
    525         }
    526 }
    527 
    528 static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst,
     524                return converter.core.cost;
     525        }
     526}
     527
     528static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
    529529                int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
    530                 NumCostCalculation func ) {
     530                PtrsCalculation func ) {
    531531        if ( 0 < diff ) {
    532532                Cost cost = convertToReferenceCost(
    533                         strict_dynamic_cast< const ast::ReferenceType * >( src )->base,
    534                         dst, (diff - 1), symtab, env, func );
     533                        strict_dynamic_cast< const ast::ReferenceType * >( src )->base, dst,
     534                        srcIsLvalue, (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                         (diff + 1), symtab, env, func );
     540                        srcIsLvalue, (diff + 1), symtab, env, func );
    541541                cost.incReference();
    542542                return cost;
     
    563563                        }
    564564                } else {
    565                         ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
     565                        ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
    566566                        src->accept( converter );
    567                         return converter.pass.cost;
     567                        return converter.core.cost;
    568568                }
    569569        } else {
     
    572572                assert( dstAsRef );
    573573                if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
    574                         if ( src->is_lvalue() ) {
     574                        if ( srcIsLvalue ) {
    575575                                if ( src->qualifiers == dstAsRef->base->qualifiers ) {
    576576                                        return Cost::reference;
     
    591591
    592592Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst,
    593             const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
    594                 NumCostCalculation func ) {
     593                bool srcIsLvalue, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
     594                PtrsCalculation func ) {
    595595        int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth();
    596         return convertToReferenceCost( src, dst, sdepth - ddepth, symtab, env, func );
     596        return convertToReferenceCost( src, dst, srcIsLvalue, sdepth - ddepth, symtab, env, func );
    597597}
    598598
     
    651651        assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
    652652
    653         cost = costCalc( refType->base, dst, symtab, env );
     653        cost = costCalc( refType->base, dst, srcIsLvalue, 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 const ast::BasicType integer( ast::BasicType::SignedInt );
    670         cost = costCalc( &integer, dst, symtab, env );
     669        static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
     670        cost = costCalc( integer, dst, srcIsLvalue, 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, symtab, env );
     682                cost = costCalc( eqv->bound, dst, srcIsLvalue, 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, symtab, env ) + Cost::safe;
     692                        cost = costCalc( type->base, dst, srcIsLvalue, symtab, env ) + Cost::safe;
    693693                }
    694694        }
     
    703703                auto dstEnd = dstAsTuple->types.end();
    704704                while ( srcIt != srcEnd && dstIt != dstEnd ) {
    705                         Cost newCost = costCalc( * srcIt++, * dstIt++, symtab, env );
     705                        Cost newCost = costCalc( * srcIt++, * dstIt++, srcIsLvalue, 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 );
    740744        }
    741745}
     
    755759                        cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
    756760                }
    757         } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
    758                 cost = Cost::zero;
    759                 cost.incSafe( maxIntCost + 2 );
    760         }
    761 }
    762 
     761        }
     762}
     763// size_t ConversionCost_new::traceId = Stats::Heap::new_stacktrace_id("ConversionCost");
    763764
    764765} // namespace ResolvExpr
  • src/ResolvExpr/ConversionCost.h

    r309d814 r4c925cd  
    7272
    7373// Some function pointer types, differ in return type.
    74 using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *,
     74using CostCalculation = std::function<Cost(const ast::Type *, const ast::Type *, bool,
    7575        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
    76 using NumCostCalculation = std::function<int(const ast::Type *, const ast::Type *,
     76using PtrsCalculation = 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;
    8384        const ast::SymbolTable & symtab;
    8485        const ast::TypeEnvironment & env;
    8586        CostCalculation costCalc;
    8687public:
     88        static size_t traceId;
    8789        Cost cost;
    8890
    89         ConversionCost_new( const ast::Type * dst, const ast::SymbolTable & symtab,
     91        ConversionCost_new( const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab,
    9092                        const ast::TypeEnvironment & env, CostCalculation costCalc ) :
    91                 dst( dst ), symtab( symtab ), env( env ), costCalc( costCalc ), cost( Cost::infinity )
     93                dst( dst ), srcIsLvalue( srcIsLvalue ), symtab( symtab ), env( env ),
     94                costCalc( costCalc ), cost( Cost::infinity )
    9295        {}
    9396
     
    110113
    111114Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,
    112         const ast::SymbolTable & indexer, const ast::TypeEnvironment & env, NumCostCalculation func );
     115        bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env,
     116        PtrsCalculation func );
    113117
    114118} // namespace ResolvExpr
  • src/ResolvExpr/CurrentObject.cc

    r309d814 r4c925cd  
    2121#include <string>                      // for string, operator<<, allocator
    2222
     23#include "AST/Copy.hpp"                // for shallowCopy
    2324#include "AST/Expr.hpp"                // for InitAlternative
    2425#include "AST/GenericSubstitution.hpp" // for genericSubstitution
    2526#include "AST/Init.hpp"                // for Designation
    2627#include "AST/Node.hpp"                // for readonly
     28#include "AST/Print.hpp"                // for readonly
    2729#include "AST/Type.hpp"
    2830#include "Common/Indenter.h"           // for Indenter, operator<<
     
    596598                SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
    597599
    598                 void setPosition( 
    599                         std::deque< ptr< Expr > >::const_iterator begin, 
     600                void setPosition(
     601                        std::deque< ptr< Expr > >::const_iterator begin,
    600602                        std::deque< ptr< Expr > >::const_iterator end
    601603                ) override {
     
    637639                        auto res = eval(expr);
    638640                        if ( ! res.second ) {
    639                                 SemanticError( location, 
     641                                SemanticError( location,
    640642                                        toString("Array designator must be a constant expression: ", expr ) );
    641643                        }
     
    644646
    645647        public:
    646                 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) 
     648                ArrayIterator( const CodeLocation & loc, const ArrayType * at )
    647649                : location( loc ), array( at ), base( at->base ) {
    648650                        PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
     
    655657
    656658                void setPosition( const Expr * expr ) {
    657                         // need to permit integer-constant-expressions, including: integer constants, 
    658                         // enumeration constants, character constants, sizeof expressions, alignof expressions, 
     659                        // need to permit integer-constant-expressions, including: integer constants,
     660                        // enumeration constants, character constants, sizeof expressions, alignof expressions,
    659661                        // cast expressions
    660662                        if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) {
     
    662664                                        index = constExpr->intValue();
    663665                                } catch ( SemanticErrorException & ) {
    664                                         SemanticError( expr, 
     666                                        SemanticError( expr,
    665667                                                "Constant expression of non-integral type in array designator: " );
    666668                                }
    667669                        } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) {
    668670                                setPosition( castExpr->arg );
    669                         } else if ( 
    670                                 dynamic_cast< const SizeofExpr * >( expr ) 
    671                                 || dynamic_cast< const AlignofExpr * >( expr ) 
     671                        } else if (
     672                                dynamic_cast< const SizeofExpr * >( expr )
     673                                || dynamic_cast< const AlignofExpr * >( expr )
    672674                        ) {
    673675                                index = 0;
    674676                        } else {
    675                                 assertf( false, 
     677                                assertf( false,
    676678                                        "bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
    677679                        }
    678680                }
    679681
    680                 void setPosition( 
    681                         std::deque< ptr< Expr > >::const_iterator begin, 
     682                void setPosition(
     683                        std::deque< ptr< Expr > >::const_iterator begin,
    682684                        std::deque< ptr< Expr > >::const_iterator end
    683685                ) override {
     
    758760                }
    759761
    760                 AggregateIterator( 
    761                         const CodeLocation & loc, const std::string k, const std::string & n, const Type * i, 
     762                AggregateIterator(
     763                        const CodeLocation & loc, const std::string k, const std::string & n, const Type * i,
    762764                        const MemberList & ms )
    763                 : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ), 
     765                : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ),
    764766                  sub( genericSubstitution( i ) ) {
    765767                        PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
     
    768770
    769771        public:
    770                 void setPosition( 
    771                         std::deque< ptr< Expr > >::const_iterator begin, 
     772                void setPosition(
     773                        std::deque< ptr< Expr > >::const_iterator begin,
    772774                        std::deque< ptr< Expr > >::const_iterator end
    773775                ) final {
     
    786788                                        return;
    787789                                }
    788                                 assertf( false, 
     790                                assertf( false,
    789791                                        "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
    790792                        } else {
    791                                 assertf( false, 
     793                                assertf( false,
    792794                                        "bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() );
    793795                        }
     
    803805                                                new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
    804806                                        // need to substitute for generic types so that casts are to concrete types
     807                                        alt.type = shallowCopy(alt.type.get());
    805808                                        PRINT( std::cerr << "  type is: " << alt.type; )
    806809                                        sub.apply( alt.type ); // also apply to designation??
     
    842845                                for ( InitAlternative & alt : ret ) {
    843846                                        PRINT( std::cerr << "iterating and adding designators" << std::endl; )
    844                                         alt.designation.get_and_mutate()->designators.emplace_front( 
     847                                        alt.designation.get_and_mutate()->designators.emplace_front(
    845848                                                new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
    846849                                }
     
    897900        class TupleIterator final : public AggregateIterator {
    898901        public:
    899                 TupleIterator( const CodeLocation & loc, const TupleType * inst ) 
    900                 : AggregateIterator( 
    901                         loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members 
     902                TupleIterator( const CodeLocation & loc, const TupleType * inst )
     903                : AggregateIterator(
     904                        loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members
    902905                ) {}
    903906
     
    926929                                return new UnionIterator{ loc, uit };
    927930                        } else {
    928                                 assertf( 
    929                                         dynamic_cast< const EnumInstType * >( aggr )
    930                                                 || dynamic_cast< const TypeInstType * >( aggr ),
     931                                assertf(
     932                                        dynamic_cast< const EnumInstType * >( type )
     933                                                || dynamic_cast< const TypeInstType * >( type ),
    931934                                        "Encountered unhandled ReferenceToType in createMemberIterator: %s",
    932935                                                toString( type ).c_str() );
     
    949952                using DesignatorChain = std::deque< ptr< Expr > >;
    950953                PRINT( std::cerr << "___findNext" << std::endl; )
    951                
     954
    952955                // find all the d's
    953956                std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts;
     
    10131016                // set new designators
    10141017                assertf( ! objStack.empty(), "empty object stack when setting designation" );
    1015                 Designation * actualDesignation = 
     1018                Designation * actualDesignation =
    10161019                        new Designation{ designation->location, DesignatorChain{d} };
    10171020                objStack.back()->setPosition( d ); // destroys d
  • src/ResolvExpr/PolyCost.cc

    r309d814 r4c925cd  
    5858
    5959// TODO: When the old PolyCost is torn out get rid of the _new suffix.
    60 struct PolyCost_new {
     60class PolyCost_new {
     61        const ast::SymbolTable &symtab;
     62public:
    6163        int result;
    62         const ast::SymbolTable &symtab;
    6364        const ast::TypeEnvironment &env_;
    6465
    65         PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) :
    66                 result( 0 ), symtab( symtab ), env_( env ) {}
     66        PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env )
     67        : symtab( symtab ), result( 0 ), env_( env ) {}
    6768
    6869        void previsit( const ast::TypeInstType * type ) {
     
    8687        ast::Pass<PolyCost_new> costing( symtab, env );
    8788        type->accept( costing );
    88         return costing.pass.result;
     89        return costing.core.result;
    8990}
    9091
  • src/ResolvExpr/PtrsAssignable.cc

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

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

    r309d814 r4c925cd  
    1919#include <utility>                 // for pair
    2020
     21#include "AST/ForallSubstitutionTable.hpp"
    2122#include "AST/Pass.hpp"
    2223#include "AST/Type.hpp"
     
    3031#include "SynTree/Visitor.h"       // for acceptAll, maybeAccept
    3132
     33#include "AST/Copy.hpp"
     34
    3235namespace ResolvExpr {
    3336
     
    3740                int resetCount = 0;
    3841                ScopedMap< std::string, std::string > nameMap;
     42        public:
     43                ast::ForallSubstitutionTable subs;
    3944
    40         public:
    4145                void reset() {
    4246                        level = 0;
     
    4448                }
    4549
    46                 using mapConstIterator = ScopedMap< std::string, std::string >::const_iterator;
    47 
    4850                void rename( TypeInstType * type ) {
    49                         mapConstIterator it = nameMap.find( type->name );
     51                        auto it = nameMap.find( type->name );
    5052                        if ( it != nameMap.end() ) {
    5153                                type->name = it->second;
     
    6567                                        // ditto for assertion names, the next level in
    6668                                        level++;
    67                                         // acceptAll( td->assertions, *this );
    68                                 } // for
    69                         } // if
     69                                }
     70                        }
    7071                }
    7172
     
    7778
    7879                const ast::TypeInstType * rename( const ast::TypeInstType * type ) {
    79                         mapConstIterator it = nameMap.find( type->name );
     80                        // re-linking of base type handled by WithForallSubstitutor
     81
     82                        // rename
     83                        auto it = nameMap.find( type->name );
    8084                        if ( it != nameMap.end() ) {
    81                                 ast::TypeInstType * mutType = ast::mutate( type );
    82                                 mutType->name = it->second;
    83                     type = mutType;
     85                                // unconditionally mutate because map will *always* have different name,
     86                                // if this mutates, will *always* have been mutated by ForallSubstitutor above
     87                                ast::TypeInstType * mut = ast::mutate( type );
     88                                mut->name = it->second;
     89                    type = mut;
    8490                        }
     91
    8592                        return type;
    8693                }
     
    8895                template<typename NodeT>
    8996                const NodeT * openLevel( const NodeT * type ) {
    90                         if ( !type->forall.empty() ) {
    91                                 nameMap.beginScope();
    92                                 // Load new names from this forall clause and perform renaming.
    93                                 NodeT * mutType = ast::mutate( type );
    94                                 for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) {
    95                                         std::ostringstream output;
    96                                         output << "_" << resetCount << "_" << level << "_" << td->name;
    97                                         std::string newname( output.str() );
    98                                         nameMap[ td->name ] = newname;
    99                                         ++level;
     97                        if ( type->forall.empty() ) return type;
    10098
    101                                         ast::TypeDecl * decl = ast::mutate( td.get() );
    102                                         decl->name = newname;
    103                                         td = decl;
    104                                 }
     99                        nameMap.beginScope();
     100
     101                        // Load new names from this forall clause and perform renaming.
     102                        NodeT * mutType = ast::mutate( type );
     103                        assert( type == mutType && "mutated type must be unique from ForallSubstitutor" );
     104                        for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) {
     105                                std::ostringstream output;
     106                                output << "_" << resetCount << "_" << level << "_" << td->name;
     107                                std::string newname =  output.str();
     108                                nameMap[ td->name ] = newname;
     109                                ++level;
     110
     111                                ast::TypeDecl * mutDecl = ast::mutate( td.get() );
     112                                assert( td == mutDecl && "mutated decl must be unique from ForallSubstitutor" );
     113                                mutDecl->name = newname;
     114                                // assertion above means `td = mutDecl;` is unnecessary
    105115                        }
     116                        // assertion above means `type = mutType;` is unnecessary
     117
    106118                        return type;
    107119                }
    108120
    109                 template<typename NodeT>
    110                 const NodeT * closeLevel( const NodeT * type ) {
    111                         if ( !type->forall.empty() ) {
    112                                 nameMap.endScope();
    113                         }
    114                         return type;
     121                void closeLevel( const ast::ParameterizedType * type ) {
     122                        if ( type->forall.empty() ) return;
     123
     124                        nameMap.endScope();
    115125                }
    116126        };
     
    119129        RenamingData renaming;
    120130
    121         struct RenameVars {
     131        struct RenameVars_old {
    122132                void previsit( TypeInstType * instType ) {
    123133                        renaming.openLevel( (Type*)instType );
     
    130140                        renaming.closeLevel( type );
    131141                }
     142        };
     143
     144        struct RenameVars_new /*: public ast::WithForallSubstitutor*/ {
     145                #warning when old RenameVars goes away, replace hack below with global pass inheriting from WithForallSubstitutor
     146                ast::ForallSubstitutionTable & subs = renaming.subs;
    132147
    133148                const ast::FunctionType * previsit( const ast::FunctionType * type ) {
     
    146161                        return renaming.rename( renaming.openLevel( type ) );
    147162                }
    148                 const ast::ParameterizedType * postvisit( const ast::ParameterizedType * type ) {
    149                         return renaming.closeLevel( type );
     163                void postvisit( const ast::ParameterizedType * type ) {
     164                        renaming.closeLevel( type );
    150165                }
    151166        };
     
    154169
    155170void renameTyVars( Type * t ) {
    156         PassVisitor<RenameVars> renamer;
     171        PassVisitor<RenameVars_old> renamer;
    157172        t->accept( renamer );
    158173}
    159174
    160175const ast::Type * renameTyVars( const ast::Type * t ) {
    161         ast::Pass<RenameVars> renamer;
    162         return t->accept( renamer );
     176        ast::Type *tc = ast::deepCopy(t);
     177        ast::Pass<RenameVars_new> renamer;
     178//      return t->accept( renamer );
     179        return tc->accept( renamer );
    163180}
    164181
  • src/ResolvExpr/ResolveTypeof.cc

    r309d814 r4c925cd  
    9999                        // replace basetypeof(<enum>) by int
    100100                        if ( dynamic_cast<EnumInstType*>(newType) ) {
    101                                 Type* newerType = 
    102                                         new BasicType{ newType->get_qualifiers(), BasicType::SignedInt, 
     101                                Type* newerType =
     102                                        new BasicType{ newType->get_qualifiers(), BasicType::SignedInt,
    103103                                        newType->attributes };
    104104                                delete newType;
    105105                                newType = newerType;
    106106                        }
    107                         newType->get_qualifiers().val 
     107                        newType->get_qualifiers().val
    108108                                = ( newType->get_qualifiers().val & ~Type::Qualifiers::Mask ) | oldQuals;
    109109                } else {
    110110                        newType->get_qualifiers().val |= oldQuals;
    111111                }
    112                
     112
    113113                return newType;
    114114        }
     
    120120                ResolveTypeof_new( const ast::SymbolTable & syms ) : localSymtab( syms ) {}
    121121
    122                 void premutate( const ast::TypeofType * ) { visit_children = false; }
     122                void previsit( const ast::TypeofType * ) { visit_children = false; }
    123123
    124                 const ast::Type * postmutate( const ast::TypeofType * typeofType ) {
     124                const ast::Type * postvisit( const ast::TypeofType * typeofType ) {
    125125                        // pass on null expression
    126126                        if ( ! typeofType->expr ) return typeofType;
     
    133133                                // typeof wrapping expression
    134134                                ast::TypeEnvironment dummy;
    135                                 ast::ptr< ast::Expr > newExpr = 
     135                                ast::ptr< ast::Expr > newExpr =
    136136                                        resolveInVoidContext( typeofType->expr, localSymtab, dummy );
    137137                                assert( newExpr->result && ! newExpr->result->isVoid() );
     
    143143                                // replace basetypeof(<enum>) by int
    144144                                if ( newType.as< ast::EnumInstType >() ) {
    145                                         newType = new ast::BasicType{ 
     145                                        newType = new ast::BasicType{
    146146                                                ast::BasicType::SignedInt, newType->qualifiers, copy(newType->attributes) };
    147147                                }
    148                                 reset_qualifiers( 
    149                                         newType, 
     148                                reset_qualifiers(
     149                                        newType,
    150150                                        ( newType->qualifiers & ~ast::CV::EquivQualifiers ) | typeofType->qualifiers );
    151151                        } else {
     
    153153                        }
    154154
    155                         return newType;
     155                        return newType.release();
    156156                }
    157157        };
  • src/ResolvExpr/Resolver.cc

    r309d814 r4c925cd  
    982982                ast::Pass<DeleteFinder_new> finder;
    983983                expr->accept( finder );
    984                 return finder.pass.delExpr;
     984                return finder.core.delExpr;
    985985        }
    986986
     
    10721072                /// Strips extraneous casts out of an expression
    10731073                struct StripCasts_new final {
    1074                         const ast::Expr * postmutate( const ast::CastExpr * castExpr ) {
     1074                        const ast::Expr * postvisit( const ast::CastExpr * castExpr ) {
    10751075                                if (
    1076                                         castExpr->isGenerated
     1076                                        castExpr->isGenerated == ast::GeneratedCast
    10771077                                        && typesCompatible( castExpr->arg->result, castExpr->result )
    10781078                                ) {
     
    11281128
    11291129                // set up and resolve expression cast to void
    1130                 ast::CastExpr * untyped = new ast::CastExpr{ expr };
     1130                ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
    11311131                CandidateRef choice = findUnfinishedKindExpression(
    11321132                        untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
     
    12361236
    12371237        public:
     1238                static size_t traceId;
    12381239                Resolver_new() = default;
    12391240                Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
     
    12661267                const ast::ConstructorInit * previsit( const ast::ConstructorInit * );
    12671268        };
    1268 
    1269         void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) {
    1270                 ast::Pass< Resolver_new > resolver;
    1271                 accept_all( translationUnit, resolver );
     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 );
    12721273        }
    12731274
     
    12991300                // default value expressions have an environment which shouldn't be there and trips up
    13001301                // later passes.
    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 >() ) {
     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 >() ) {
    13061307                                if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) {
    13071308                                        if ( init->value->env == nullptr ) continue;
    13081309                                        // clone initializer minus the initializer environment
    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 );
     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);
    13171320                                }
    13181321                        }
    13191322                }
    1320                 return ret.get();
     1323                mutate_field(functionDecl, &ast::FunctionDecl::type, mutType);
     1324                return functionDecl;
    13211325        }
    13221326
     
    13411345                // in case we decide to allow nested enums
    13421346                GuardValue( inEnumDecl );
    1343                 inEnumDecl = false;
     1347                inEnumDecl = true;
    13441348        }
    13451349
  • src/ResolvExpr/SatisfyAssertions.cpp

    r309d814 r4c925cd  
    99// Author           : Aaron B. Moss
    1010// Created On       : Mon Jun 10 17:45:00 2019
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Mon Jun 10 17:45:00 2019
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Oct  1 13:56:00 2019
     13// Update Count     : 2
    1414//
    1515
     
    188188
    189189                                matches.emplace_back(
    190                                         cdata, adjType, std::move( newEnv ), std::move( newNeed ), std::move( have ),
     190                                        cdata, adjType, std::move( newEnv ), std::move( have ), std::move( newNeed ),
    191191                                        std::move( newOpen ), crntResnSlot );
    192192                        }
     
    229229                InferMatcher( InferCache & inferred ) : inferred( inferred ) {}
    230230
    231                 const ast::Expr * postmutate( const ast::Expr * expr ) {
     231                const ast::Expr * postvisit( const ast::Expr * expr ) {
    232232                        // Skip if no slots to find
    233                         if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr;
    234 
     233                        if ( !expr->inferred.hasSlots() ) return expr;
     234                        // if ( expr->inferred.mode != ast::Expr::InferUnion::Slots ) return expr;
     235                        std::vector<UniqueId> missingSlots;
    235236                        // find inferred parameters for resolution slots
    236                         ast::InferredParams newInferred;
     237                        ast::InferredParams * newInferred = new ast::InferredParams();
    237238                        for ( UniqueId slot : expr->inferred.resnSlots() ) {
    238239                                // fail if no matching assertions found
    239240                                auto it = inferred.find( slot );
    240241                                if ( it == inferred.end() ) {
    241                                         assert(!"missing assertion");
     242                                        std::cerr << "missing assertion " << slot << std::endl;
     243                                        missingSlots.push_back(slot);
     244                                        continue;
    242245                                }
    243246
     
    245248                                for ( auto & entry : it->second ) {
    246249                                        // recurse on inferParams of resolved expressions
    247                                         entry.second.expr = postmutate( entry.second.expr );
    248                                         auto res = newInferred.emplace( entry );
     250                                        entry.second.expr = postvisit( entry.second.expr );
     251                                        auto res = newInferred->emplace( entry );
    249252                                        assert( res.second && "all assertions newly placed" );
    250253                                }
     
    252255
    253256                        ast::Expr * ret = mutate( expr );
    254                         ret->inferred.set_inferParams( std::move( newInferred ) );
     257                        ret->inferred.set_inferParams( newInferred );
     258                        if (!missingSlots.empty()) ret->inferred.resnSlots() = missingSlots;
    255259                        return ret;
    256260                }
     
    299303                        Cost cost;
    300304
    301                         OutType( 
    302                                 const ast::TypeEnvironment & e, const ast::OpenVarSet & o, 
     305                        OutType(
     306                                const ast::TypeEnvironment & e, const ast::OpenVarSet & o,
    303307                                const std::vector< DeferRef > & as, const ast::SymbolTable & symtab )
    304308                        : env( e ), open( o ), assns( as ), cost( Cost::zero ) {
     
    306310                                for ( const DeferRef & assn : assns ) {
    307311                                        // compute conversion cost from satisfying decl to assertion
    308                                         cost += computeConversionCost( 
    309                                                 assn.match.adjType, assn.decl->get_type(), symtab, env );
    310                                        
     312                                        cost += computeConversionCost(
     313                                                assn.match.adjType, assn.decl->get_type(), false, symtab, env );
     314
    311315                                        // mark vars+specialization on function-type assertions
    312                                         const ast::FunctionType * func = 
     316                                        const ast::FunctionType * func =
    313317                                                GenPoly::getFunctionType( assn.match.cdata.id->get_type() );
    314318                                        if ( ! func ) continue;
     
    317321                                                cost.decSpec( specCost( param->get_type() ) );
    318322                                        }
    319                                        
     323
    320324                                        cost.incVar( func->forall.size() );
    321                                        
     325
    322326                                        for ( const ast::TypeDecl * td : func->forall ) {
    323327                                                cost.decSpec( td->assertions.size() );
     
    329333                };
    330334
    331                 CandidateEnvMerger( 
    332                         const ast::TypeEnvironment & env, const ast::OpenVarSet & open, 
     335                CandidateEnvMerger(
     336                        const ast::TypeEnvironment & env, const ast::OpenVarSet & open,
    333337                        const ast::SymbolTable & syms )
    334338                : crnt(), envs{ env }, opens{ open }, symtab( syms ) {}
  • src/ResolvExpr/SatisfyAssertions.hpp

    r309d814 r4c925cd  
    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

    r309d814 r4c925cd  
    1010// Created On       : Tue Oct 02 15:50:00 2018
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jun 19 10:43:00 2019
    13 // Update Count     : 2
    14 //
    15 
     12// Last Modified On : Wed Jul  3 11:07:00 2019
     13// Update Count     : 3
     14//
     15
     16#include <cassert>
    1617#include <limits>
    1718#include <list>
     
    129130                        typename std::add_pointer<ast::Type const *(typename T::value_type const &)>::type;
    130131
     132                #warning Should use a standard maybe_accept
     133                void maybe_accept( ast::Type const * type ) {
     134                        if ( type ) {
     135                                auto node = type->accept( *visitor );
     136                                assert( node == nullptr || node == type );
     137                        }
     138                }
     139
    131140                // Update the minimum to the new lowest non-none value.
    132141                template<typename T>
     
    134143                        for ( const auto & node : list ) {
    135144                                count = -1;
    136                                 mapper( node )->accept( *visitor );
     145                                maybe_accept( mapper( node ) );
    137146                                if ( count != -1 && count < minimum ) minimum = count;
    138147                        }
     
    208217        }
    209218        ast::Pass<SpecCounter> counter;
    210         type->accept( *counter.pass.visitor );
    211         return counter.pass.get_count();
     219        type->accept( counter );
     220        return counter.core.get_count();
    212221}
    213222
  • src/ResolvExpr/Unify.cc

    r309d814 r4c925cd  
    2525#include <vector>
    2626
     27#include "AST/Copy.hpp"
    2728#include "AST/Decl.hpp"
    2829#include "AST/Node.hpp"
    2930#include "AST/Pass.hpp"
     31#include "AST/Print.hpp"
    3032#include "AST/Type.hpp"
    3133#include "AST/TypeEnvironment.hpp"
     
    135137                findOpenVars( newSecond, open, closed, need, have, FirstOpen );
    136138
    137                 return unifyExact(
    138                         newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     139                return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
    139140        }
    140141
     
    148149                newFirst->get_qualifiers() = Type::Qualifiers();
    149150                newSecond->get_qualifiers() = Type::Qualifiers();
    150 ///   std::cerr << "first is ";
    151 ///   first->print( std::cerr );
    152 ///   std::cerr << std::endl << "second is ";
    153 ///   second->print( std::cerr );
    154 ///   std::cerr << std::endl << "newFirst is ";
    155 ///   newFirst->print( std::cerr );
    156 ///   std::cerr << std::endl << "newSecond is ";
    157 ///   newSecond->print( std::cerr );
    158 ///   std::cerr << std::endl;
     151
    159152                bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    160153                delete newFirst;
     
    170163                ast::AssertionSet need, have;
    171164
    172                 ast::ptr<ast::Type> newFirst{ first }, newSecond{ second };
    173                 env.apply( newFirst );
    174                 env.apply( newSecond );
    175                 reset_qualifiers( newFirst );
    176                 reset_qualifiers( newSecond );
     165                ast::Type * newFirst  = shallowCopy( first  );
     166                ast::Type * newSecond = shallowCopy( second );
     167                newFirst ->qualifiers = {};
     168                newSecond->qualifiers = {};
     169                ast::ptr< ast::Type > t1_(newFirst );
     170                ast::ptr< ast::Type > t2_(newSecond);
     171
     172                ast::ptr< ast::Type > subFirst = env.apply(newFirst).node;
     173                ast::ptr< ast::Type > subSecond = env.apply(newSecond).node;
    177174
    178175                return unifyExact(
    179                         newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     176                        subFirst,
     177                        subSecond,
     178                        newEnv, need, have, open, noWiden(), symtab );
    180179        }
    181180
     
    326325
    327326        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;
    333327                AssertionSet::iterator i = assertions.find( assert );
    334328                if ( i != assertions.end() ) {
    335 ///     std::cerr << "found it!" << std::endl;
    336329                        i->second.isUsed = true;
    337330                } // if
     
    709702                const ast::SymbolTable & symtab;
    710703        public:
     704                static size_t traceId;
    711705                bool result;
    712706
     
    943937
    944938        private:
    945                 template< typename RefType >
    946                 const RefType * handleRefType( const RefType * inst, const ast::Type * other ) {
     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 ) {
    947943                        // check that the other type is compatible and named the same
    948                         auto otherInst = dynamic_cast< const RefType * >( other );
    949                         result = otherInst && inst->name == otherInst->name;
     944                        auto otherInst = dynamic_cast< const XInstType * >( other );
     945                        this->result = otherInst && inst->name == otherInst->name;
    950946                        return otherInst;
    951947                }
     
    968964                }
    969965
    970                 template< typename RefType >
    971                 void handleGenericRefType( const RefType * inst, const ast::Type * other ) {
     966                template< typename XInstType >
     967                void handleGenericRefType( const XInstType * inst, const ast::Type * other ) {
    972968                        // check that other type is compatible and named the same
    973                         const RefType * inst2 = handleRefType( inst, other );
    974                         if ( ! inst2 ) return;
     969                        const XInstType * otherInst = handleRefType( inst, other );
     970                        if ( ! this->result ) return;
    975971
    976972                        // check that parameters of types unify, if any
    977973                        const std::vector< ast::ptr< ast::Expr > > & params = inst->params;
    978                         const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params;
     974                        const std::vector< ast::ptr< ast::Expr > > & params2 = otherInst->params;
    979975
    980976                        auto it = params.begin();
     
    11401136        };
    11411137
     1138        // size_t Unify_new::traceId = Stats::Heap::new_stacktrace_id("Unify_new");
    11421139        bool unify(
    11431140                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     
    11881185                        ast::Pass<Unify_new> comparator{ type2, env, need, have, open, widen, symtab };
    11891186                        type1->accept( comparator );
    1190                         return comparator.pass.result;
     1187                        return comparator.core.result;
    11911188                }
    11921189        }
     
    12021199                // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and
    12031200                // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1
    1204                 ast::ptr<ast::Type> t1{ type1 }, t2{ type2 };
    1205                 reset_qualifiers( t1 );
    1206                 reset_qualifiers( t2 );
     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);
    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 
    12111209                        // if exact unification on unqualified types, try to merge qualifiers
    12121210                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
    1213                                 common = type1;
    1214                                 reset_qualifiers( common, q1 | q2 );
     1211                                t1->qualifiers = q1 | q2;
     1212                                common = t1;
    12151213                                return true;
    12161214                        } else {
     
    12191217
    12201218                } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {
    1221                         t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
    1222 
    12231219                        // no exact unification, but common type
    1224                         reset_qualifiers( common, q1 | q2 );
     1220                        auto c = shallowCopy(common.get());
     1221                        c->qualifiers = q1 | q2;
     1222                        common = c;
    12251223                        return true;
    12261224                } else {
  • src/ResolvExpr/typeops.h

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

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

    r309d814 r4c925cd  
    106106                bool isVoid = false;
    107107
    108                 void premutate( const ast::FunctionDecl * ) { visit_children = false; }
     108                void previsit( const ast::FunctionDecl * ) { visit_children = false; }
    109109
    110                 const ast::DeclWithType * postmutate( const ast::FunctionDecl * func ) {
     110                const ast::DeclWithType * postvisit( const ast::FunctionDecl * func ) {
    111111                        return new ast::ObjectDecl{
    112112                                func->location, func->name, new ast::PointerType{ func->type }, nullptr,
     
    114114                }
    115115
    116                 void premutate( const ast::ArrayType * ) { visit_children = false; }
     116                void previsit( const ast::ArrayType * ) { visit_children = false; }
    117117
    118                 const ast::Type * postmutate( const ast::ArrayType * array ) {
     118                const ast::Type * postvisit( const ast::ArrayType * array ) {
    119119                        return new ast::PointerType{
    120120                                array->base, array->dimension, array->isVarLen, array->isStatic,
     
    122122                }
    123123
    124                 void premutate( const ast::VoidType * ) { isVoid = true; }
     124                void previsit( const ast::VoidType * ) { isVoid = true; }
    125125
    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; }
     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; }
    137137        };
    138138} // anonymous namespace
     
    141141        ast::Pass< FixFunction_new > fixer;
    142142        dwt = dwt->accept( fixer );
    143         isVoid |= fixer.pass.isVoid;
     143        isVoid |= fixer.core.isVoid;
    144144        return dwt;
    145145}
  • src/SymTab/Mangler.cc

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

    r309d814 r4c925cd  
    3434
    3535ParamEntry::ParamEntry( const ParamEntry &other ) :
    36                 decl( other.decl ), declptr( maybeClone( other.declptr ) ), actualType( maybeClone( other.actualType ) ), formalType( maybeClone( other.formalType ) ), expr( maybeClone( other.expr ) ) {
     36                decl( other.decl ), declptr( 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

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

    r309d814 r4c925cd  
    129129                        for ( const ast::Expr * expr : tupleExpr->exprs ) {
    130130                                exprs.emplace_back( applyCast( expr, false ) );
    131                                 //exprs.emplace_back( ast::ptr< ast::Expr >( applyCast( expr, false ) ) );
    132131                        }
    133132                        if ( first ) {
     
    148147        }
    149148
    150         const ast::Expr * postmutate( const ast::UniqueExpr * node ) {
     149        const ast::Expr * postvisit( const ast::UniqueExpr * node ) {
    151150                // move cast into unique expr so that the unique expr has type T& rather than
    152151                // type T. In particular, this transformation helps with generating the
     
    167166        }
    168167
    169         const ast::Expr * postmutate( const ast::TupleIndexExpr * tupleExpr ) {
     168        const ast::Expr * postvisit( const ast::TupleIndexExpr * tupleExpr ) {
    170169                // tuple index expr needs to be rebuilt to ensure that the type of the
    171170                // field is consistent with the type of the tuple expr, since the field
     
    180179        ast::Pass<CastExploderCore> exploder;
    181180        expr = expr->accept( exploder );
    182         if ( ! exploder.pass.foundUniqueExpr ) {
     181        if ( ! exploder.core.foundUniqueExpr ) {
    183182                expr = new ast::CastExpr{ expr, new ast::ReferenceType{ expr->result } };
    184183        }
  • src/Tuples/Explode.h

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

    r309d814 r4c925cd  
    465465                                        // resolve ctor/dtor for the new object
    466466                                        ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit(
    467                                                         InitTweak::genCtorInit( location, ret ), spotter.crntFinder.symtab );
     467                                                        InitTweak::genCtorInit( location, ret ), spotter.crntFinder.localSyms );
    468468                                        // remove environments from subexpressions of stmtExpr
    469469                                        ast::Pass< EnvRemover > rm{ env };
     
    504504
    505505                        std::vector< ast::ptr< ast::Expr > > match() override {
    506                                 static UniqueName lhsNamer( "__massassign_L" );
    507                                 static UniqueName rhsNamer( "__massassign_R" );
     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" );
    508509                                // empty tuple case falls into this matcher
    509510                                assert( lhs.empty() ? rhs.empty() : rhs.size() <= 1 );
     
    534535
    535536                        std::vector< ast::ptr< ast::Expr > > match() override {
    536                                 static UniqueName lhsNamer( "__multassign_L" );
    537                                 static UniqueName rhsNamer( "__multassign_R" );
     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" );
    538540
    539541                                if ( lhs.size() != rhs.size() ) return {};
     
    560562                                        // resolve the cast expression so that rhsCand return type is bound by the cast
    561563                                        // type as needed, and transfer the resulting environment
    562                                         ResolvExpr::CandidateFinder finder{ spotter.crntFinder.symtab, env };
     564                                        ResolvExpr::CandidateFinder finder{ spotter.crntFinder.localSyms, env };
    563565                                        finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() );
    564566                                        assert( finder.candidates.size() == 1 );
     
    609611                                        // explode the LHS so that each field of a tuple-valued expr is assigned
    610612                                        ResolvExpr::CandidateList lhs;
    611                                         explode( *lhsCand, crntFinder.symtab, back_inserter(lhs), true );
     613                                        explode( *lhsCand, crntFinder.localSyms, back_inserter(lhs), true );
    612614                                        for ( ResolvExpr::CandidateRef & cand : lhs ) {
    613615                                                // each LHS value must be a reference - some come in with a cast, if not
     
    629631                                                        if ( isTuple( rhsCand->expr ) ) {
    630632                                                                // multiple assignment
    631                                                                 explode( *rhsCand, crntFinder.symtab, back_inserter(rhs), true );
     633                                                                explode( *rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
    632634                                                                matcher.reset(
    633635                                                                        new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
     
    648650                                                        // multiple assignment
    649651                                                        ResolvExpr::CandidateList rhs;
    650                                                         explode( rhsCand, crntFinder.symtab, back_inserter(rhs), true );
     652                                                        explode( rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
    651653                                                        matcher.reset(
    652654                                                                new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
     
    678680                                )
    679681
    680                                 ResolvExpr::CandidateFinder finder{ crntFinder.symtab, matcher->env };
     682                                ResolvExpr::CandidateFinder finder{ crntFinder.localSyms, matcher->env };
    681683
    682684                                try {
  • src/Tuples/TupleExpansion.cc

    r309d814 r4c925cd  
    323323                std::vector<ast::ptr<ast::Type>> types;
    324324                ast::CV::Qualifiers quals{
    325                         ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Lvalue |
     325                        ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict |
    326326                        ast::CV::Atomic | ast::CV::Mutex };
    327327
  • src/Tuples/Tuples.cc

    r309d814 r4c925cd  
    4343        };
    4444        struct ImpurityDetectorIgnoreUnique : public ImpurityDetector {
     45                using ImpurityDetector::previsit;
    4546                void previsit( ast::UniqueExpr const * ) {
    4647                        visit_children = false;
     
    5253                ast::Pass<Detector> detector;
    5354                expr->accept( detector );
    54                 return detector.pass.maybeImpure;
     55                return detector.core.maybeImpure;
    5556        }
    5657} // namespace
  • src/config.h.in

    r309d814 r4c925cd  
    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
    2933
    3034/* Major.Minor */
  • src/main.cc

    r309d814 r4c925cd  
    3131using namespace std;
    3232
    33 
     33#include "AST/Convert.hpp"
    3434#include "CompilationState.h"
    3535#include "../config.h"                      // for CFA_LIBDIR
     
    340340                } // if
    341341
    342                 PASS( "Resolve", ResolvExpr::resolve( translationUnit ) );
     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
    343350                if ( exprp ) {
    344351                        dump( translationUnit );
     
    458465        { "prototypes", no_argument, nullptr, 'p' },
    459466        { "deterministic-out", no_argument, nullptr, 'd' },
     467        { "old-ast", no_argument, nullptr, 'O'},
     468        { "new-ast", no_argument, nullptr, 'A'},
    460469        { "print", required_argument, nullptr, 'P' },
    461470        { "prelude-dir", required_argument, nullptr, PreludeDir },
     
    479488        "generate prototypes for prelude functions",            // -p
    480489        "don't print output that isn't deterministic",        // -d
     490        "Use the old-ast",                                    // -O
     491        "Use the new-ast",                                    // -A
    481492        "print",                                              // -P
    482493        "<directory> prelude directory for debug/nodebug",      // no flag
     
    584595                        break;
    585596                  case 'd':                                     // don't print non-deterministic output
    586                     deterministic_output = true;
     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;
    587604                        break;
    588605                  case 'P':                                                                             // print options
Note: See TracChangeset for help on using the changeset viewer.