Changes in / [fe63ae6:56c8b86]


Ignore:
Files:
43 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/coroutine.cfa

    rfe63ae6 r56c8b86  
    4646
    4747//-----------------------------------------------------------------------------
    48 EHM_VIRTUAL_TABLE(SomeCoroutineCancelled, std_coroutine_cancelled);
     48FORALL_DATA_INSTANCE(CoroutineCancelled, (coroutine_t &), (coroutine_t))
     49
     50forall(T &)
     51void mark_exception(CoroutineCancelled(T) *) {}
    4952
    5053forall(T &)
     
    6871
    6972        // TODO: Remove explitate vtable set once trac#186 is fixed.
    70         SomeCoroutineCancelled except;
    71         except.virtual_table = &std_coroutine_cancelled;
     73        CoroutineCancelled(T) except;
     74        except.virtual_table = &get_exception_vtable(&except);
    7275        except.the_coroutine = &cor;
    7376        except.the_exception = except;
    74         // Why does this need a cast?
    75         throwResume (SomeCoroutineCancelled &)except;
     77        throwResume except;
    7678
    7779        except->virtual_table->free( except );
  • libcfa/src/concurrency/coroutine.hfa

    rfe63ae6 r56c8b86  
    2222//-----------------------------------------------------------------------------
    2323// Exception thrown from resume when a coroutine stack is cancelled.
    24 EHM_EXCEPTION(SomeCoroutineCancelled)(
    25         void * the_coroutine;
    26         exception_t * the_exception;
    27 );
    28 
    29 EHM_EXTERN_VTABLE(SomeCoroutineCancelled, std_coroutine_cancelled);
    30 
    31 EHM_FORALL_EXCEPTION(CoroutineCancelled, (coroutine_t &), (coroutine_t)) (
     24FORALL_DATA_EXCEPTION(CoroutineCancelled, (coroutine_t &), (coroutine_t)) (
    3225        coroutine_t * the_coroutine;
    3326        exception_t * the_exception;
     
    4437// Anything that implements this trait can be resumed.
    4538// Anything that is resumed is a coroutine.
    46 trait is_coroutine(T & | IS_RESUMPTION_EXCEPTION(SomeCoroutineCancelled)) {
     39trait is_coroutine(T & | IS_RESUMPTION_EXCEPTION(CoroutineCancelled, (T))) {
    4740        void main(T & this);
    4841        $coroutine * get_coroutine(T & this);
  • libcfa/src/concurrency/kernel.cfa

    rfe63ae6 r56c8b86  
    359359                                #if !defined(__CFA_NO_STATISTICS__)
    360360                                        __tls_stats()->ready.threads.threads++;
    361                                         __push_stat( __tls_stats(), __tls_stats()->ready.threads.threads, false, "Processor", this );
    362361                                #endif
    363362                                // This is case 2, the racy case, someone tried to run this thread before it finished blocking
     
    377376        #if !defined(__CFA_NO_STATISTICS__)
    378377                __tls_stats()->ready.threads.threads--;
    379                 __push_stat( __tls_stats(), __tls_stats()->ready.threads.threads, false, "Processor", this );
    380378        #endif
    381379
     
    457455                if( kernelTLS().this_stats ) {
    458456                        __tls_stats()->ready.threads.threads++;
    459                         __push_stat( __tls_stats(), __tls_stats()->ready.threads.threads, false, "Processor", kernelTLS().this_processor );
    460457                }
    461458                else {
    462459                        __atomic_fetch_add(&cl->stats->ready.threads.threads, 1, __ATOMIC_RELAXED);
    463                         __push_stat( cl->stats, cl->stats->ready.threads.threads, true, "Cluster", cl );
    464460                }
    465461        #endif
  • libcfa/src/concurrency/kernel/startup.cfa

    rfe63ae6 r56c8b86  
    268268                        __print_stats( st, mainProcessor->print_stats, "Processor ", mainProcessor->name, (void*)mainProcessor );
    269269                }
    270                 #if defined(CFA_STATS_ARRAY)
    271                         __flush_stat( st, "Processor", mainProcessor );
    272                 #endif
    273270        #endif
    274271
     
    351348                        __print_stats( &local_stats, proc->print_stats, "Processor ", proc->name, (void*)proc );
    352349                }
    353                 #if defined(CFA_STATS_ARRAY)
    354                         __flush_stat( &local_stats, "Processor", proc );
    355                 #endif
    356350        #endif
    357351
     
    621615                        __print_stats( this.stats, this.print_stats, "Cluster", this.name, (void*)&this );
    622616                }
    623                 #if defined(CFA_STATS_ARRAY)
    624                         __flush_stat( this.stats, "Cluster", &this );
    625                 #endif
    626617                free( this.stats );
    627618        #endif
  • libcfa/src/concurrency/stats.cfa

    rfe63ae6 r56c8b86  
    55#include <inttypes.h>
    66#include "bits/debug.hfa"
    7 #include "bits/locks.hfa"
    87#include "stats.hfa"
    98
     
    4544                        stats->io.calls.errors.busy = 0;
    4645                        stats->io.poller.sleeps     = 0;
    47                 #endif
    48 
    49                 #if defined(CFA_STATS_ARRAY)
    50                         stats->array.values = alloc(CFA_STATS_ARRAY);
    51                         stats->array.cnt = 0;
    5246                #endif
    5347        }
     
    157151                #endif
    158152        }
    159 
    160         #if defined(CFA_STATS_ARRAY)
    161                 extern "C" {
    162                         #include <stdio.h>
    163                         #include <errno.h>
    164                         #include <sys/stat.h>
    165                         #include <fcntl.h>
    166                 }
    167 
    168                 void __flush_stat( struct __stats_t * this, const char * name, void * handle) {
    169                         int ret = mkdir(".cfadata", 0755);
    170                         if(ret < 0 && errno != EEXIST) abort("Failed to create directory .cfadata: %d\n", errno);
    171 
    172                         char filename[100];
    173                         snprintf(filename, 100, ".cfadata/%s%p.data", name, handle);
    174 
    175                         int fd = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0644);
    176                         if(fd < 0) abort("Failed to create file %s: %d\n", filename, errno);
    177 
    178                         for(i; this->array.cnt) {
    179                                 char line[100];
    180                                 size_t n = snprintf(line, 100, "%llu, %lld\n", this->array.values[i].ts, this->array.values[i].value);
    181                                 write(fd, line, n);
    182                         }
    183 
    184                         this->array.cnt = 0;
    185                         close(fd);
    186                 }
    187 
    188                 static __spinlock_t stats_lock;
    189 
    190                 void __push_stat( struct __stats_t * this, int64_t value, bool external, const char * name, void * handle ) {
    191                         if(external) lock(stats_lock __cfaabi_dbg_ctx2);
    192 
    193                         if( this->array.cnt >= CFA_STATS_ARRAY ) __flush_stat( this, name, handle );
    194 
    195                         size_t idx = this->array.cnt;
    196                         this->array.cnt++;
    197 
    198                         if(external) unlock(stats_lock);
    199 
    200                         this->array.values[idx].ts = rdtscl();
    201                         this->array.values[idx].value = value;
    202                 }
    203         #endif
    204153#endif
  • libcfa/src/concurrency/stats.hfa

    rfe63ae6 r56c8b86  
    11#pragma once
    2 
    3 // #define CFA_STATS_ARRAY 10000
    42
    53#include <stdint.h>
     
    111109        #endif
    112110
    113         #if defined(CFA_STATS_ARRAY)
    114                 struct __stats_elem_t {
    115                         long long int ts;
    116                         int64_t value;
    117                 };
    118         #endif
    119 
    120111        struct __attribute__((aligned(128))) __stats_t {
    121112                __stats_readQ_t ready;
     
    123114                        __stats_io_t    io;
    124115                #endif
    125 
    126                 #if defined(CFA_STATS_ARRAY)
    127                         struct {
    128                                 __stats_elem_t * values;
    129                                 volatile size_t cnt;
    130                         } array;
    131                 #endif
    132 
    133116        };
    134117
     
    136119        void __tally_stats( struct __stats_t *, struct __stats_t * );
    137120        void __print_stats( struct __stats_t *, int, const char *, const char *, void * );
    138         #if defined(CFA_STATS_ARRAY)
    139                 void __push_stat ( struct __stats_t *, int64_t value, bool external, const char * name, void * handle);
    140                 void __flush_stat( struct __stats_t *, const char *, void * );
    141         #else
    142                 static inline void __push_stat ( struct __stats_t *, int64_t, bool, const char *, void * ) {}
    143                 static inline void __flush_stat( struct __stats_t *, const char *, void * ) {}
    144         #endif
    145121#endif
    146122
  • libcfa/src/concurrency/thread.cfa

    rfe63ae6 r56c8b86  
    6262}
    6363
    64 EHM_VIRTUAL_TABLE(SomeThreadCancelled, std_thread_cancelled);
     64FORALL_DATA_INSTANCE(ThreadCancelled, (thread_t &), (thread_t))
    6565
    6666forall(T &)
     
    7373forall(T &)
    7474const char * msg(ThreadCancelled(T) *) {
    75         return "ThreadCancelled(...)";
     75        return "ThreadCancelled";
    7676}
    7777
    7878forall(T &)
    7979static void default_thread_cancel_handler(ThreadCancelled(T) & ) {
    80         // Improve this error message, can I do formatting?
    8180        abort( "Unhandled thread cancellation.\n" );
    8281}
    8382
    84 static void default_thread_cancel_handler(SomeThreadCancelled & ) {
    85         // Improve this error message, can I do formatting?
    86         abort( "Unhandled thread cancellation.\n" );
    87 }
    88 
    89 forall(T & | is_thread(T) | IS_EXCEPTION(SomeThreadCancelled))
     83forall(T & | is_thread(T) | IS_EXCEPTION(ThreadCancelled, (T)))
    9084void ?{}( thread_dtor_guard_t & this,
    91                 T & thrd, void(*cancelHandler)(SomeThreadCancelled &)) {
    92         $monitor * m = get_monitor(thrd);
     85                T & thrd, void(*cancelHandler)(ThreadCancelled(T) &)) {
     86        $monitor * m = get_monitor(thrd);
    9387        $thread * desc = get_thread(thrd);
    9488
    9589        // Setup the monitor guard
    9690        void (*dtor)(T& mutex this) = ^?{};
    97         bool join = cancelHandler != (void(*)(SomeThreadCancelled&))0;
     91        bool join = cancelHandler != (void(*)(ThreadCancelled(T)&))0;
    9892        (this.mg){&m, (void(*)())dtor, join};
    9993
     
    109103        }
    110104        desc->state = Cancelled;
    111         void(*defaultResumptionHandler)(SomeThreadCancelled &) =
     105        void(*defaultResumptionHandler)(ThreadCancelled(T) &) =
    112106                join ? cancelHandler : default_thread_cancel_handler;
    113107
     108        ThreadCancelled(T) except;
    114109        // TODO: Remove explitate vtable set once trac#186 is fixed.
    115         SomeThreadCancelled except;
    116         except.virtual_table = &std_thread_cancelled;
     110        except.virtual_table = &get_exception_vtable(&except);
    117111        except.the_thread = &thrd;
    118112        except.the_exception = __cfaehm_cancellation_exception( cancellation );
    119         // Why is this cast required?
    120         throwResume (SomeThreadCancelled &)except;
     113        throwResume except;
    121114
    122115        except.the_exception->virtual_table->free( except.the_exception );
     
    165158
    166159//-----------------------------------------------------------------------------
    167 forall(T & | is_thread(T) | IS_RESUMPTION_EXCEPTION(SomeThreadCancelled))
     160forall(T & | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)))
    168161T & join( T & this ) {
    169162        thread_dtor_guard_t guard = { this, defaultResumptionHandler };
  • libcfa/src/concurrency/thread.hfa

    rfe63ae6 r56c8b86  
    3232};
    3333
    34 EHM_EXCEPTION(SomeThreadCancelled) (
    35         void * the_thread;
    36         exception_t * the_exception;
    37 );
    38 
    39 EHM_EXTERN_VTABLE(SomeThreadCancelled, std_thread_cancelled);
    40 
    41 EHM_FORALL_EXCEPTION(ThreadCancelled, (thread_t &), (thread_t)) (
     34FORALL_DATA_EXCEPTION(ThreadCancelled, (thread_t &), (thread_t)) (
    4235        thread_t * the_thread;
    4336        exception_t * the_exception;
     
    8679};
    8780
    88 forall( T & | is_thread(T) | IS_EXCEPTION(SomeThreadCancelled) )
    89 void ?{}( thread_dtor_guard_t & this, T & thrd, void(*)(SomeThreadCancelled &) );
     81forall( T & | is_thread(T) | IS_EXCEPTION(ThreadCancelled, (T)) )
     82void ?{}( thread_dtor_guard_t & this, T & thrd, void(*)(ThreadCancelled(T) &) );
    9083void ^?{}( thread_dtor_guard_t & this );
    9184
     
    132125//----------
    133126// join
    134 forall( T & | is_thread(T) | IS_RESUMPTION_EXCEPTION(SomeThreadCancelled) )
     127forall( T & | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled, (T)) )
    135128T & join( T & this );
    136129
  • libcfa/src/exception.c

    rfe63ae6 r56c8b86  
    1010// Created On       : Mon Jun 26 15:13:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Feb 24 13:40:00 2021
    13 // Update Count     : 36
     12// Last Modified On : Tue Oct 27 16:27:00 2020
     13// Update Count     : 35
    1414//
    1515
     
    2626#include "concurrency/invoke.h"
    2727#include "stdhdr/assert.h"
    28 #include "virtual.h"
    2928
    3029#if defined( __ARM_ARCH )
     
    4746const _Unwind_Exception_Class __cfaehm_exception_class = 0x4c50575500414643;
    4847
    49 // Base Exception type id:
    50 struct __cfa__parent_vtable __cfatid_exception_t = {
    51         NULL,
     48// Base exception vtable is abstract, you should not have base exceptions.
     49struct __cfaehm_base_exception_t_vtable
     50                ___cfaehm_base_exception_t_vtable_instance = {
     51        .parent = NULL,
     52        .size = 0,
     53        .copy = NULL,
     54        .free = NULL,
     55        .msg = NULL
    5256};
    5357
  • libcfa/src/exception.h

    rfe63ae6 r56c8b86  
    1010// Created On       : Mon Jun 26 15:11:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Apr  8 15:20:00 2021
    13 // Update Count     : 12
     12// Last Modified On : Tue Oct 27 14:45:00 2020
     13// Update Count     : 11
    1414//
    1515
     
    2929struct __cfaehm_base_exception_t;
    3030typedef struct __cfaehm_base_exception_t exception_t;
    31 struct __cfa__parent_vtable;
    3231struct __cfaehm_base_exception_t_vtable {
    33         const struct __cfa__parent_vtable * __cfavir_typeid;
     32        const struct __cfaehm_base_exception_t_vtable * parent;
    3433        size_t size;
    3534        void (*copy)(struct __cfaehm_base_exception_t *this,
     
    4140        struct __cfaehm_base_exception_t_vtable const * virtual_table;
    4241};
    43 extern struct __cfa__parent_vtable __cfatid_exception_t;
     42extern struct __cfaehm_base_exception_t_vtable
     43        ___cfaehm_base_exception_t_vtable_instance;
    4444
    4545
     
    104104        /* The first field must be a pointer to a virtual table.
    105105         * That virtual table must be a decendent of the base exception virtual table.
    106          * The virtual table must point at the prober type-id.
    107          * None of these can be enforced in an assertion.
    108106         */
     107        virtualT const & get_exception_vtable(exceptT *);
     108        // Always returns the virtual table for this type (associated types hack).
    109109};
    110110
  • libcfa/src/exception.hfa

    rfe63ae6 r56c8b86  
    1010// Created On       : Thu Apr  7 10:25:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Apr  8 15:16:00 2021
    13 // Update Count     : 4
     12// Last Modified On : Tue Aug  4 16:22:00 2020
     13// Update Count     : 3
    1414//
    1515
     
    1818// -----------------------------------------------------------------------------------------------
    1919
    20 // EHM_EXCEPTION(exception_name)(fields...);
    21 // Create an exception (a virtual structure that inherits from exception_t)
    22 // with the given name and fields.
    23 #define EHM_EXCEPTION(exception_name) \
    24         _EHM_TYPE_ID_STRUCT(exception_name, ); \
    25         _EHM_TYPE_ID_VALUE(exception_name, ); \
    26         _EHM_VIRTUAL_TABLE_STRUCT(exception_name, , ); \
    27         _EHM_EXCEPTION_STRUCT(exception_name, , )
    28 
    29 // EHM_EXTERN_VTABLE(exception_name, table_name);
    30 // Forward declare a virtual table called table_name for exception_name type.
    31 #define EHM_EXTERN_VTABLE(exception_name, table_name) \
    32         _EHM_EXTERN_VTABLE(exception_name, , table_name)
    33 
    34 // EHM_VIRTUAL_TABLE(exception_name, table_name);
    35 // Define a virtual table called table_name for exception_name type.
    36 #define EHM_VIRTUAL_TABLE(exception_name, table_name) \
    37         _EHM_DEFINE_COPY(exception_name, ) \
    38         _EHM_DEFINE_MSG(exception_name, ) \
    39         _EHM_VIRTUAL_TABLE(exception_name, , table_name)
    40 
    41 // EHM_FORALL_EXCEPTION(exception_name, (assertions), (parameters))(fields...);
    42 // As EHM_EXCEPTION but for polymorphic types instead of monomorphic ones.
    43 // The assertions list should include all polymorphic parameters and
    44 // assertions inside a parentisized list. Parameters should include all the
    45 // polymorphic parameter names inside a parentisized list (same order).
    46 #define EHM_FORALL_EXCEPTION(exception_name, assertions, parameters) \
    47         _EHM_TYPE_ID_STRUCT(exception_name, forall assertions); \
    48         _EHM_VIRTUAL_TABLE_STRUCT(exception_name, forall assertions, parameters); \
    49         _EHM_EXCEPTION_STRUCT(exception_name, forall assertions, parameters)
    50 
    51 // EHM_FORALL_EXTERN_VTABLE(exception_name, (arguments), table_name);
    52 // As EHM_EXTERN_VTABLE but for polymorphic types instead of monomorphic ones.
    53 // Arguments should be the parentisized list of polymorphic arguments.
    54 #define EHM_FORALL_EXTERN_VTABLE(exception_name, arguments, table_name) \
    55         _EHM_EXTERN_VTABLE(exception_name, arguments, table_name)
    56 
    57 // EHM_FORALL_VIRTUAL_TABLE(exception_name, (arguments), table_name);
    58 // As EHM_VIRTUAL_TABLE but for polymorphic types instead of monomorphic ones.
    59 // Arguments should be the parentisized list of polymorphic arguments.
    60 #define EHM_FORALL_VIRTUAL_TABLE(exception_name, arguments, table_name) \
    61         _EHM_TYPE_ID_VALUE(exception_name, arguments); \
    62         _EHM_DEFINE_COPY(exception_name, arguments) \
    63         _EHM_DEFINE_MSG(exception_name, arguments) \
    64         _EHM_VIRTUAL_TABLE(exception_name, arguments, table_name)
    65 
    66 #define EHM_TYPE_ID(exception_name) _EHM_TYPE_ID_TYPE(exception_name)
    67 
    68 #define EHM_MATCH_ALL __cfa__parent_vtable
     20// TRIVIAL_EXCEPTION_DECLARATION(exception_name);
     21// Declare a trivial exception, one that adds no fields or features.
     22// This will make the exception visible and may go in a .hfa or .cfa file.
     23#define TRIVIAL_EXCEPTION_DECLARATION(...) \
     24        _EXC_DISPATCH(_TRIVIAL_EXCEPTION_DECLARATION, __VA_ARGS__)
     25
     26// TRIVIAL_EXCEPTION_INSTANCE(exception_name);
     27// Create the trival exception. This must be used exactly once and should be used in a .cfa file,
     28// as it creates the unique instance of the virtual table.
     29#define TRIVIAL_EXCEPTION_INSTANCE(...) _EXC_DISPATCH(_TRIVIAL_EXCEPTION_INSTANCE, __VA_ARGS__)
     30
     31// TRIVIAL_EXCEPTION(exception_name[, parent_name]);
     32// Does both of the above, a short hand if the exception is only used in one .cfa file.
     33// For legacy reasons this is the only one that official supports having a parent other than the
     34// base exception. This feature may be removed or changed.
     35#define TRIVIAL_EXCEPTION(...) \
     36        _EXC_DISPATCH(_TRIVIAL_EXCEPTION_DECLARATION, __VA_ARGS__); \
     37        _EXC_DISPATCH(_TRIVIAL_EXCEPTION_INSTANCE, __VA_ARGS__)
     38
     39// FORALL_TRIVIAL_EXCEPTION(exception_name, (assertions...), (parameters...));
     40// Forward declare a polymorphic but otherwise trivial exception type. You must provide the entire
     41// assertion list (exactly what would go in the forall clause) and parameters list (only the
     42// parameter names from the assertion list, same order and comma seperated). This should be
     43// visible where ever use the exception. This just generates the polymorphic framework, see
     44// POLY_VTABLE_DECLARATION to allow instantiations.
     45#define FORALL_TRIVIAL_EXCEPTION(exception_name, assertions, parameters) \
     46        _FORALL_TRIVIAL_EXCEPTION(exception_name, __cfaehm_base_exception_t, assertions, parameters, )
     47
     48// FORALL_TRIVIAL_INSTANCE(exception_name, (assertions...), (parameters...))
     49// Create the forall trivial exception. The assertion list and parameters must match.
     50// There must be exactly one use of this in a program for each exception type. This just
     51// generates the polymorphic framework, see POLY_VTABLE_INSTANCE to allow instantiations.
     52#define FORALL_TRIVIAL_INSTANCE(exception_name, assertions, parameters) \
     53        _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters)
     54
     55// DATA_EXCEPTION(exception_name)(fields...);
     56// Forward declare an exception that adds fields but no features. The added fields go in the
     57// second argument list. The virtual table instance must be provided later (see VTABLE_INSTANCE).
     58#define DATA_EXCEPTION(...) _EXC_DISPATCH(_DATA_EXCEPTION, __VA_ARGS__)
     59
     60// FORALL_DATA_EXCEPTION(exception_name, (assertions...), (parameters...))(fields...);
     61// Define a polymorphic exception that adds fields but no additional features. The assertion list
     62// and matching parameters must match. Then you can give the list of fields. This should be
     63// visible where ever you use the exception. This just generates the polymorphic framework, see
     64// POLY_VTABLE_DECLARATION to allow instantiations.
     65#define FORALL_DATA_EXCEPTION(exception_name, assertions, parameters) \
     66        _FORALL_DATA_EXCEPTION(exception_name, __cfaehm_base_exception_t, assertions, parameters, )
     67
     68// FORALL_DATA_INSTANCE(exception_name, (assertions...), (parameters...))
     69// Create a polymorphic data exception. The assertion list and parameters must match. This should
     70// appear once in each program. This just generates the polymorphic framework, see
     71// POLY_VTABLE_INSTANCE to allow instantiations.
     72#define FORALL_DATA_INSTANCE(exception_name, assertions, parameters) \
     73        _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters)
     74
     75// VTABLE_DECLARATION(exception_name)([new_features...]);
     76// Declare a virtual table type for an exception with exception_name. You may also add features
     77// (fields on the virtual table) by including them in the second list.
     78#define VTABLE_DECLARATION(...) _EXC_DISPATCH(_VTABLE_DECLARATION, __VA_ARGS__)
     79
     80// VTABLE_INSTANCE(exception_name)(msg [, others...]);
     81// Create the instance of the virtual table. There must be exactly one instance of a virtual table
     82// for each exception type. This fills in most of the fields of the virtual table (uses ?=? and
     83// ^?{}) but you must provide the message function and any other fields added in the declaration.
     84#define VTABLE_INSTANCE(...) _EXC_DISPATCH(_VTABLE_INSTANCE, __VA_ARGS__)
     85
     86// FORALL_VTABLE_DECLARATION(exception_name, (assertions...), (parameters...))([new_features...]);
     87// Declare a polymorphic virtual table type for an exception with exception_name, the given
     88// assertions and parameters. You may also add features (fields on the virtual table). This just
     89// generates the polymorphic framework, see POLY_VTABLE_DECLARATION to allow instantiations.
     90#define FORALL_VTABLE_DECLARATION(exception_name, assertions, parameters) \
     91        _FORALL_VTABLE_DECLARATION(exception_name, __cfaehm_base_exception_t, assertions, parameters, )
     92
     93// POLY_VTABLE_DECLARATION(exception_name, types...);
     94// Declares that an instantiation for this exception exists for the given types. This should be
     95// visible anywhere you use the instantiation of the exception is used.
     96#define POLY_VTABLE_DECLARATION(exception_name, ...) \
     97        VTABLE_TYPE(exception_name)(__VA_ARGS__) const & get_exception_vtable(exception_name(__VA_ARGS__) *); \
     98        extern VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name)
     99
     100// POLY_VTABLE_INSTANCE(exception_name, types...)(msg [, others...]);
     101// Creates an instantiation for the given exception for the given types. This should occur only
     102// once in the entire program. You must fill in all features, message and any others given in the
     103// initial declaration.
     104#define POLY_VTABLE_INSTANCE(exception_name, ...) \
     105        _POLY_VTABLE_INSTANCE(exception_name, __cfaehm_base_exception_t, __VA_ARGS__)
     106
     107// VTABLE_TYPE(exception_name) | VTABLE_NAME(exception_name)
     108// Get the name of the vtable type or the name of the vtable instance for an exception type.
     109#define VTABLE_TYPE(exception_name) struct _GLUE2(exception_name,_vtable)
     110#define VTABLE_NAME(exception_name) _GLUE3(_,exception_name,_vtable_instance)
     111
     112// VTABLE_FIELD(exception_name);
     113// FORALL_VTABLE_FIELD(exception_name, (parameters-or-types));
     114// The declaration of the virtual table field. Should be the first declaration in a virtual type.
     115#define VTABLE_FIELD(exception_name) VTABLE_TYPE(exception_name) const * virtual_table
     116#define FORALL_VTABLE_FIELD(exception_name, parameters) \
     117        VTABLE_TYPE(exception_name) parameters const * virtual_table
     118
     119// VTABLE_INIT(object_reference, exception_name);
     120// Sets a virtual table field on an object to the virtual table instance for the type.
     121#define VTABLE_INIT(this, exception_name) (this).virtual_table = &VTABLE_NAME(exception_name)
     122
     123// VTABLE_ASSERTION(exception_name, (parameters...))
     124// The assertion that there is an instantiation of the vtable for the exception and types.
     125#define VTABLE_ASSERTION(exception_name, parameters) \
     126        { VTABLE_TYPE(exception_name) parameters VTABLE_NAME(exception_name); }
    69127
    70128// IS_EXCEPTION(exception_name [, (...parameters)])
     
    77135#define IS_TERMINATION_EXCEPTION(...) _IS_EXCEPTION(is_termination_exception, __VA_ARGS__, , ~)
    78136
    79 // Macros starting with a leading underscore are internal.
    80 
    81 // Create an exception type definition. must be tailing, can be polymorphic.
    82 #define _EHM_EXCEPTION_STRUCT(exception_name, forall_clause, parameters) \
    83         forall_clause struct exception_name { \
    84                 _EHM_VTABLE_TYPE(exception_name) parameters const * virtual_table; \
    85                 _CLOSE
    86 
    87 // Create a (possibly polymorphic) virtual table forward declaration.
    88 #define _EHM_EXTERN_VTABLE(exception_name, arguments, table_name) \
    89         extern const _EHM_VTABLE_TYPE(exception_name) arguments table_name
    90 
    91 // Create a (possibly polymorphic) virtual table definition.
    92 #define _EHM_VIRTUAL_TABLE(exception_type, arguments, table_name) \
    93         const _EHM_VTABLE_TYPE(exception_type) arguments table_name @= { \
    94                 .__cfavir_typeid : &_EHM_TYPE_ID_NAME(exception_type), \
    95                 .size : sizeof(struct exception_type arguments), \
    96                 .copy : copy, \
    97                 .^?{} : ^?{}, \
    98                 .msg : msg, \
     137// All internal helper macros begin with an underscore.
     138#define _CLOSE(...) __VA_ARGS__ }
     139#define _GLUE2(left, right) left##right
     140#define _GLUE3(left, middle, right) left##middle##right
     141#define _EXC_DISPATCH(to, ...) to(__VA_ARGS__,__cfaehm_base_exception_t,)
     142#define _UNPACK(...) __VA_ARGS__
     143
     144#define _TRIVIAL_EXCEPTION_DECLARATION(exception_name, parent_name, ...) \
     145        _VTABLE_DECLARATION(exception_name, parent_name)(); \
     146        struct exception_name { \
     147                VTABLE_FIELD(exception_name); \
     148        }; \
     149        void ?{}(exception_name & this); \
     150        const char * _GLUE2(exception_name,_msg)(exception_name * this)
     151
     152#define _TRIVIAL_EXCEPTION_INSTANCE(exception_name, parent_name, ...) \
     153        void ?{}(exception_name & this) { \
     154                VTABLE_INIT(this, exception_name); \
     155        } \
     156        const char * _GLUE2(exception_name,_msg)(exception_name * this) { \
     157                return #exception_name; \
     158        } \
     159        _VTABLE_INSTANCE(exception_name, parent_name,)(_GLUE2(exception_name,_msg))
     160
     161#define _FORALL_TRIVIAL_EXCEPTION(exception_name, parent_name, assertions, \
     162                parameters, parent_parameters) \
     163        _FORALL_VTABLE_DECLARATION(exception_name, parent_name, assertions, \
     164                parameters, parent_parameters)(); \
     165        forall assertions struct exception_name { \
     166                FORALL_VTABLE_FIELD(exception_name, parameters); \
     167        }; \
     168        _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters)
     169
     170#define _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) \
     171        forall(_UNPACK assertions | \
     172                is_exception(exception_name parameters, VTABLE_TYPE(exception_name) parameters)) \
     173        void ?{}(exception_name parameters & this)
     174
     175#define _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters) \
     176        _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) { \
     177                (this).virtual_table = &get_exception_vtable(&this); \
    99178        }
    100179
    101 // Create a (possibly polymorphic) copy function from an assignment operator.
    102 #define _EHM_DEFINE_FORALL_COPY(exception_name, forall_clause, parameters) \
    103         forall_clause void copy(exception_name parameters * this, \
    104                         exception_name parameters * that) { \
    105                 *this = *that; \
    106         }
    107 
    108 #define _EHM_DEFINE_COPY(exception_name, arguments) \
    109         void copy(exception_name arguments * this, exception_name arguments * that) { \
    110                 *this = *that; \
    111         }
    112 
    113 // Create a (possibly polymorphic) msg function
    114 #define _EHM_DEFINE_FORALL_MSG(exception_name, forall_clause, parameters) \
    115         forall_clause const char * msg(exception_name parameters * this) { \
    116                 return #exception_name #parameters; \
    117         }
    118 
    119 #define _EHM_DEFINE_MSG(exception_name, arguments) \
    120         const char * msg(exception_name arguments * this) { \
    121                 return #exception_name #arguments; \
    122         }
    123 
    124 // Produces the C compatable name of the virtual table type for a virtual type.
    125 #define _EHM_VTABLE_TYPE(type_name) struct _GLUE2(type_name,_vtable)
    126 
    127 // Create the vtable type for exception name.
    128 #define _EHM_VIRTUAL_TABLE_STRUCT(exception_name, forall_clause, parameters) \
    129         forall_clause struct exception_name; \
    130         forall_clause _EHM_VTABLE_TYPE(exception_name) { \
    131                 _EHM_TYPE_ID_TYPE(exception_name) parameters const * __cfavir_typeid; \
     180#define _DATA_EXCEPTION(exception_name, parent_name, ...) \
     181        _VTABLE_DECLARATION(exception_name, parent_name)(); \
     182        struct exception_name { \
     183                VTABLE_FIELD(exception_name); \
     184                _CLOSE
     185
     186#define _FORALL_DATA_EXCEPTION(exception_name, parent_name, \
     187                assertions, parameters, parent_parameters) \
     188        _FORALL_VTABLE_DECLARATION(exception_name, parent_name, \
     189                assertions, parameters, parent_parameters)(); \
     190        _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters); \
     191        forall assertions struct exception_name { \
     192                FORALL_VTABLE_FIELD(exception_name, parameters); \
     193                _CLOSE
     194
     195#define _VTABLE_DECLARATION(exception_name, parent_name, ...) \
     196        struct exception_name; \
     197        VTABLE_TYPE(exception_name); \
     198        VTABLE_TYPE(exception_name) const & get_exception_vtable(exception_name *); \
     199        extern VTABLE_TYPE(exception_name) VTABLE_NAME(exception_name); \
     200        VTABLE_TYPE(exception_name) { \
     201                VTABLE_TYPE(parent_name) const * parent; \
     202                size_t size; \
     203                void (*copy)(exception_name * this, exception_name * other); \
     204                void (*^?{})(exception_name & this); \
     205                const char * (*msg)(exception_name * this); \
     206                _CLOSE
     207
     208#define _VTABLE_INSTANCE(exception_name, parent_name, ...) \
     209        VTABLE_TYPE(exception_name) const & get_exception_vtable(exception_name *) { \
     210                return VTABLE_NAME(exception_name); \
     211        } \
     212        void _GLUE2(exception_name,_copy)(exception_name * this, exception_name * other) { \
     213                *this = *other; \
     214        } \
     215        VTABLE_TYPE(exception_name) VTABLE_NAME(exception_name) @= { \
     216                &VTABLE_NAME(parent_name), sizeof(exception_name), \
     217                _GLUE2(exception_name,_copy), ^?{}, \
     218                _CLOSE
     219
     220#define _FORALL_VTABLE_DECLARATION(exception_name, parent_name, assertions, \
     221                parameters, parent_parameters) \
     222        forall assertions struct exception_name; \
     223        forall assertions VTABLE_TYPE(exception_name) { \
     224                VTABLE_TYPE(parent_name) parent_parameters const * parent; \
    132225                size_t size; \
    133226                void (*copy)(exception_name parameters * this, exception_name parameters * other); \
    134227                void (*^?{})(exception_name parameters & this); \
    135228                const char * (*msg)(exception_name parameters * this); \
    136         }
    137 
    138 // Define the function required to satify the trait for exceptions.
    139 #define _EHM_TRAIT_FUNCTION(exception_name, forall_clause, parameters) \
    140         forall_clause inline void mark_exception( \
    141                 exception_name parameters const &, \
    142                 _EHM_VTABLE_TYPE(exception_name) parameters const &) {} \
    143 
    144 #define _EHM_TRAIT_FUNCTION2(exception_name, forall_clause, parameters) \
    145         forall_clause _EHM_VTABLE_TYPE(exception_name) parameters const & \
    146                         get_exception_vtable(exception_name parameters const & this)
    147 
    148 #define __EHM_TRAIT_FUNCTION(exception_name, forall_clause, parameters) \
    149         forall_clause inline _EHM_VTABLE_TYPE(exception_name) parameters const & \
    150                         get_exception_vtable(exception_name parameters const & this) { \
    151                 /* This comes before the structure definition, but we know the offset. */ \
    152                 /* return (_EHM_VTABLE_TYPE(exception_name) parameters const &)this; */ \
    153                 assert(false); \
    154         }
    155 
    156 // Generates a new type-id structure. This is used to mangle the name of the
    157 // type-id instance so it also includes polymorphic information. Must be the
    158 // direct decendent of exception_t.
    159 // The second field is used to recover type information about the exception.
    160 #define _EHM_TYPE_ID_STRUCT(exception_name, forall_clause) \
    161         forall_clause _EHM_TYPE_ID_TYPE(exception_name) { \
    162                 __cfa__parent_vtable const * parent; \
    163         }
    164 
    165 // Generate a new type-id value.
    166 #define _EHM_TYPE_ID_VALUE(exception_name, arguments) \
    167         __attribute__(( section(".gnu.linkonce." "__cfatid_" #exception_name) )) \
    168         _EHM_TYPE_ID_TYPE(exception_name) arguments const \
    169                         _EHM_TYPE_ID_NAME(exception_name) = { \
    170                 &__cfatid_exception_t, \
    171         }
    172 
    173 // _EHM_TYPE_ID_STRUCT and _EHM_TYPE_ID_VALUE are the two that would need to
    174 // be updated to extend the hierarchy if we are still using macros when that
    175 // is added.
    176 
    177 // Produce the C compatable name of the type-id type for an exception type.
    178 #define _EHM_TYPE_ID_TYPE(exception_name) \
    179         struct _GLUE2(__cfatid_struct_, exception_name)
    180 
    181 // Produce the name of the instance of the type-id for an exception type.
    182 #define _EHM_TYPE_ID_NAME(exception_name) _GLUE2(__cfatid_,exception_name)
     229                _CLOSE
     230
     231#define _POLY_VTABLE_INSTANCE(exception_name, parent_name, ...) \
     232        extern VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name); \
     233        VTABLE_TYPE(exception_name)(__VA_ARGS__) const & get_exception_vtable( \
     234                        exception_name(__VA_ARGS__) *) { \
     235                return VTABLE_NAME(exception_name); \
     236        } \
     237        void _GLUE2(exception_name,_copy)( \
     238                        exception_name(__VA_ARGS__) * this, exception_name(__VA_ARGS__) * other) { \
     239                *this = *other; \
     240        } \
     241        VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name) @= { \
     242                &VTABLE_NAME(parent_name), sizeof(exception_name(__VA_ARGS__)), \
     243                _GLUE2(exception_name,_copy), ^?{}, \
     244                _CLOSE
    183245
    184246#define _IS_EXCEPTION(kind, exception_name, parameters, ...) \
    185         kind(exception_name parameters, _EHM_VTABLE_TYPE(exception_name) parameters)
    186 
    187 // Internal helper macros:
    188 #define _CLOSE(...) __VA_ARGS__ }
    189 #define _GLUE2(left, right) left##right
     247        kind(exception_name parameters, VTABLE_TYPE(exception_name) parameters)
  • libcfa/src/fstream.cfa

    rfe63ae6 r56c8b86  
    321321
    322322
    323 EHM_VIRTUAL_TABLE(Open_Failure, Open_Failure_main_table);
    324323void ?{}( Open_Failure & this, ofstream & ostream ) {
    325         this.virtual_table = &Open_Failure_main_table;
     324        VTABLE_INIT(this, Open_Failure);
    326325        this.ostream = &ostream;
    327326        this.tag = 1;
    328327}
    329328void ?{}( Open_Failure & this, ifstream & istream ) {
    330         this.virtual_table = &Open_Failure_main_table;
     329        VTABLE_INIT(this, Open_Failure);
    331330        this.istream = &istream;
    332331        this.tag = 0;
    333332}
     333const char * Open_Failure_msg(Open_Failure * this) {
     334        return "Open_Failure";
     335}
     336VTABLE_INSTANCE(Open_Failure)(Open_Failure_msg);
    334337void throwOpen_Failure( ofstream & ostream ) {
    335338        Open_Failure exc = { ostream };
  • libcfa/src/fstream.hfa

    rfe63ae6 r56c8b86  
    133133
    134134
    135 EHM_EXCEPTION(Open_Failure)(
     135DATA_EXCEPTION(Open_Failure)(
    136136        union {
    137137                ofstream * ostream;
  • libcfa/src/virtual.c

    rfe63ae6 r56c8b86  
    1515
    1616#include "virtual.h"
    17 #include "assert.h"
    1817
    1918int __cfa__is_parent( struct __cfa__parent_vtable const * parent,
    2019        struct __cfa__parent_vtable const * child ) {
    21         assert( child );
    2220        do {
    2321                if ( parent == child )
     
    3028void * __cfa__virtual_cast( struct __cfa__parent_vtable const * parent,
    3129        struct __cfa__parent_vtable const * const * child ) {
    32         assert( child );
    3330        return (__cfa__is_parent(parent, *child)) ? (void *)child : (void *)0;
    3431}
  • src/AST/Expr.cpp

    rfe63ae6 r56c8b86  
    260260}
    261261
    262 ConstantExpr * ConstantExpr::from_string( const CodeLocation & loc, const std::string & str ) {
    263         const Type * charType = new BasicType( BasicType::Char );
    264         // Adjust the length of the string for the terminator.
    265         const Expr * strSize = from_ulong( loc, str.size() + 1 );
    266         const Type * strType = new ArrayType( charType, strSize, FixedLen, StaticDim );
    267         const std::string strValue = "\"" + str + "\"";
    268         return new ConstantExpr( loc, strType, strValue, std::nullopt );
    269 }
    270 
    271262ConstantExpr * ConstantExpr::null( const CodeLocation & loc, const Type * ptrType ) {
    272263        return new ConstantExpr{
  • src/AST/Expr.hpp

    rfe63ae6 r56c8b86  
    438438        long long int intValue() const;
    439439
    440         /// Generates a boolean constant of the given bool.
     440        /// generates a boolean constant of the given bool
    441441        static ConstantExpr * from_bool( const CodeLocation & loc, bool b );
    442         /// Generates an integer constant of the given int.
     442        /// generates an integer constant of the given int
    443443        static ConstantExpr * from_int( const CodeLocation & loc, int i );
    444         /// Generates an integer constant of the given unsigned long int.
     444        /// generates an integer constant of the given unsigned long int
    445445        static ConstantExpr * from_ulong( const CodeLocation & loc, unsigned long i );
    446         /// Generates a string constant from the given string (char type, unquoted string).
    447         static ConstantExpr * from_string( const CodeLocation & loc, const std::string & string );
    448         /// Generates a null pointer value for the given type. void * if omitted.
     446        /// generates a null pointer value for the given type. void * if omitted.
    449447        static ConstantExpr * null( const CodeLocation & loc, const Type * ptrType = nullptr );
    450448
  • src/Concurrency/Keywords.cc

    rfe63ae6 r56c8b86  
    4242
    4343namespace Concurrency {
    44         inline static std::string getTypeIdName( std::string const & exception_name ) {
    45                 return exception_name.empty() ? std::string() : Virtual::typeIdType( exception_name );
    46         }
    4744        inline static std::string getVTableName( std::string const & exception_name ) {
    48                 return exception_name.empty() ? std::string() : Virtual::vtableTypeName( exception_name );
     45                return exception_name.empty() ? std::string() : Virtual::vtableTypeName(exception_name);
    4946        }
    5047
     
    7875                  type_name( type_name ), field_name( field_name ), getter_name( getter_name ),
    7976                  context_error( context_error ), exception_name( exception_name ),
    80                   typeid_name( getTypeIdName( exception_name ) ),
    8177                  vtable_name( getVTableName( exception_name ) ),
    8278                  needs_main( needs_main ), cast_target( cast_target ) {}
     
    8884
    8985                void handle( StructDecl * );
    90                 void addTypeId( StructDecl * );
    9186                void addVtableForward( StructDecl * );
    9287                FunctionDecl * forwardDeclare( StructDecl * );
     
    10499                const std::string context_error;
    105100                const std::string exception_name;
    106                 const std::string typeid_name;
    107101                const std::string vtable_name;
    108102                bool needs_main;
     
    112106                FunctionDecl * dtor_decl = nullptr;
    113107                StructDecl * except_decl = nullptr;
    114                 StructDecl * typeid_decl = nullptr;
    115108                StructDecl * vtable_decl = nullptr;
    116109        };
     
    399392                else if ( !except_decl && exception_name == decl->name && decl->body ) {
    400393                        except_decl = decl;
    401                 }
    402                 else if ( !typeid_decl && typeid_name == decl->name && decl->body ) {
    403                         typeid_decl = decl;
    404394                }
    405395                else if ( !vtable_decl && vtable_name == decl->name && decl->body ) {
     
    458448                if( !dtor_decl ) SemanticError( decl, context_error );
    459449
    460                 if ( !exception_name.empty() ) {
    461                         if( !typeid_decl ) SemanticError( decl, context_error );
    462                         if( !vtable_decl ) SemanticError( decl, context_error );
    463 
    464                         addTypeId( decl );
    465                         addVtableForward( decl );
    466                 }
     450                addVtableForward( decl );
    467451                FunctionDecl * func = forwardDeclare( decl );
    468452                ObjectDecl * field = addField( decl );
     
    470454        }
    471455
    472         void ConcurrentSueKeyword::addTypeId( StructDecl * decl ) {
    473                 assert( typeid_decl );
    474                 StructInstType typeid_type( Type::Const, typeid_decl );
    475                 typeid_type.parameters.push_back( new TypeExpr(
    476                         new StructInstType( noQualifiers, decl )
     456        void ConcurrentSueKeyword::addVtableForward( StructDecl * decl ) {
     457                if ( vtable_decl ) {
     458                        std::list< Expression * > poly_args = {
     459                                new TypeExpr( new StructInstType( noQualifiers, decl ) ),
     460                        };
     461                        declsToAddBefore.push_back( Virtual::makeGetExceptionForward(
     462                                vtable_decl->makeInst( poly_args ),
     463                                except_decl->makeInst( poly_args )
    477464                        ) );
    478                 declsToAddBefore.push_back( Virtual::makeTypeIdInstance( &typeid_type ) );
    479         }
    480 
    481         void ConcurrentSueKeyword::addVtableForward( StructDecl * decl ) {
    482                 assert( vtable_decl );
    483                 std::list< Expression * > poly_args = {
    484                         new TypeExpr( new StructInstType( noQualifiers, decl ) ),
    485                 };
    486                 declsToAddBefore.push_back( Virtual::makeGetExceptionForward(
    487                         vtable_decl->makeInst( poly_args ),
    488                         except_decl->makeInst( poly_args )
    489                 ) );
    490                 declsToAddBefore.push_back( Virtual::makeVtableForward(
    491                         vtable_decl->makeInst( move( poly_args ) ) ) );
     465                        declsToAddBefore.push_back( Virtual::makeVtableForward(
     466                                vtable_decl->makeInst( move( poly_args ) ) ) );
     467                // Its only an error if we want a vtable and don't have one.
     468                } else if ( ! vtable_name.empty() ) {
     469                        SemanticError( decl, context_error );
     470                }
    492471        }
    493472
  • src/SynTree/Constant.cc

    rfe63ae6 r56c8b86  
    4242}
    4343
    44 Constant Constant::from_string( const std::string & str ) {
    45         Type * charType = new BasicType( noQualifiers, BasicType::Char );
    46         // Adjust the length of the string for the terminator.
    47         Expression * strSize = new ConstantExpr( Constant::from_ulong( str.size() + 1 ) );
    48         Type * strType = new ArrayType( noQualifiers, charType, strSize, false, false );
    49         const std::string strValue = "\"" + str + "\"";
    50         return Constant( strType, strValue, std::nullopt );
    51 }
    52 
    5344Constant Constant::null( Type * ptrtype ) {
    5445        if ( nullptr == ptrtype ) {
  • src/SynTree/Constant.h

    rfe63ae6 r56c8b86  
    4747        /// generates an integer constant of the given unsigned long int
    4848        static Constant from_ulong( unsigned long i );
    49         /// generates a string constant from the given string (char type, unquoted string)
    50         static Constant from_string( const std::string & string );
    5149
    5250        /// generates a null pointer value for the given type. void * if omitted.
  • src/Virtual/ExpandCasts.cc

    rfe63ae6 r56c8b86  
    3232namespace Virtual {
    3333
    34 static bool is_prefix( const std::string & prefix, const std::string& entire ) {
    35         size_t const p_size = prefix.size();
    36         return (p_size < entire.size() && prefix == entire.substr(0, p_size));
    37 }
    38 
    39 static bool is_type_id_object( const ObjectDecl * objectDecl ) {
    40         const std::string & objectName = objectDecl->name;
    41         return is_prefix( "__cfatid_", objectName );
    42 }
    43 
    4434        // Indented until the new ast code gets added.
    4535
     
    7666        };
    7767
     68        /* Currently virtual depends on the rather brittle name matching between
     69         * a (strict/explicate) virtual type, its vtable type and the vtable
     70         * instance.
     71         * A stronger implementation, would probably keep track of those triads
     72         * and use that information to create better error messages.
     73         */
     74
     75        namespace {
     76
     77        std::string get_vtable_name( std::string const & name ) {
     78                return name + "_vtable";
     79        }
     80
     81        std::string get_vtable_inst_name( std::string const & name ) {
     82                return std::string("_") + get_vtable_name( name ) + "_instance";
     83        }
     84
     85        std::string get_vtable_name_root( std::string const & name ) {
     86                return name.substr(0, name.size() - 7 );
     87        }
     88
     89        std::string get_vtable_inst_name_root( std::string const & name ) {
     90                return get_vtable_name_root( name.substr(1, name.size() - 10 ) );
     91        }
     92
     93        bool is_vtable_inst_name( std::string const & name ) {
     94                return 17 < name.size() &&
     95                        name == get_vtable_inst_name( get_vtable_inst_name_root( name ) );
     96        }
     97
     98        } // namespace
     99
    78100        class VirtualCastCore {
    79                 CastExpr * cast_to_type_id( Expression * expr, int level_of_indirection ) {
     101                Type * pointer_to_pvt(int level_of_indirection) {
    80102                        Type * type = new StructInstType(
    81103                                Type::Qualifiers( Type::Const ), pvt_decl );
     
    83105                                type = new PointerType( noQualifiers, type );
    84106                        }
    85                         return new CastExpr( expr, type );
     107                        return type;
    86108                }
    87109
     
    119141
    120142        void VirtualCastCore::premutate( ObjectDecl * objectDecl ) {
    121                 if ( is_type_id_object( objectDecl ) ) {
    122                         // Multiple definitions should be fine because of linkonce.
    123                         indexer.insert( objectDecl );
     143                if ( is_vtable_inst_name( objectDecl->get_name() ) ) {
     144                        if ( ObjectDecl * existing = indexer.insert( objectDecl ) ) {
     145                                std::string msg = "Repeated instance of virtual table, original found at: ";
     146                                msg += existing->location.filename;
     147                                msg += ":" + toString( existing->location.first_line );
     148                                SemanticError( objectDecl->location, msg );
     149                        }
    124150                }
    125151        }
     
    144170        }
    145171
    146         /// Get the base type from a pointer or reference.
    147         const Type * getBaseType( const Type * type ) {
    148                 if ( auto target = dynamic_cast<const PointerType *>( type ) ) {
    149                         return target->base;
    150                 } else if ( auto target = dynamic_cast<const ReferenceType *>( type ) ) {
    151                         return target->base;
     172        /// Get the virtual table type used in a virtual cast.
     173        Type * getVirtualTableType( const VirtualCastExpr * castExpr ) {
     174                const Type * objectType;
     175                if ( auto target = dynamic_cast<const PointerType *>( castExpr->result ) ) {
     176                        objectType = target->base;
     177                } else if ( auto target = dynamic_cast<const ReferenceType *>( castExpr->result ) ) {
     178                        objectType = target->base;
    152179                } else {
    153                         return nullptr;
    154                 }
    155         }
    156 
    157         /* Attempt to follow the "head" field of the structure to get the...
    158          * Returns nullptr on error, otherwise owner must free returned node.
    159          */
    160         StructInstType * followHeadPointerType(
    161                         const StructInstType * oldType,
    162                         const std::string& fieldName,
    163                         const CodeLocation& errorLocation ) {
    164 
    165                 // First section of the function is all about trying to fill this variable in.
    166                 StructInstType * newType = nullptr;
    167                 {
    168                         const StructDecl * oldDecl = oldType->baseStruct;
    169                         assert( oldDecl );
    170 
    171                         // Helper function for throwing semantic errors.
    172                         auto throwError = [&fieldName, &errorLocation, &oldDecl](const std::string& message) {
    173                                 const std::string& context = "While following head pointer of " +
    174                                         oldDecl->name + " named '" + fieldName + "': ";
    175                                 SemanticError( errorLocation, context + message );
    176                         };
    177 
    178                         if ( oldDecl->members.empty() ) {
    179                                 throwError( "Type has no fields." );
    180                         }
    181                         const Declaration * memberDecl = oldDecl->members.front();
     180                        castError( castExpr, "Virtual cast type must be a pointer or reference type." );
     181                }
     182                assert( objectType );
     183
     184                const StructInstType * structType = dynamic_cast<const StructInstType *>( objectType );
     185                if ( nullptr == structType ) {
     186                        castError( castExpr, "Virtual cast type must refer to a structure type." );
     187                }
     188                const StructDecl * structDecl = structType->baseStruct;
     189                assert( structDecl );
     190
     191                const ObjectDecl * fieldDecl = nullptr;
     192                if ( 0 < structDecl->members.size() ) {
     193                        const Declaration * memberDecl = structDecl->members.front();
    182194                        assert( memberDecl );
    183                         const ObjectDecl * fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl );
    184                         assert( fieldDecl );
    185                         if ( fieldName != fieldDecl->name ) {
    186                                 throwError( "Head field did not have expected name." );
    187                         }
    188 
    189                         const Type * fieldType = fieldDecl->type;
    190                         if ( nullptr == fieldType ) {
    191                                 throwError( "Could not get head field." );
    192                         }
    193                         const PointerType * ptrType = dynamic_cast<const PointerType *>( fieldType );
    194                         if ( nullptr == ptrType ) {
    195                                 throwError( "First field is not a pointer type." );
    196                         }
    197                         assert( ptrType->base );
    198                         newType = dynamic_cast<StructInstType *>( ptrType->base );
    199                         if ( nullptr == newType ) {
    200                                 throwError( "First field does not point to a structure type." );
    201                         }
    202                 }
    203 
    204                 // Now we can look into copying it.
    205                 newType = newType->clone();
    206                 if ( ! oldType->parameters.empty() ) {
    207                         deleteAll( newType->parameters );
    208                         newType->parameters.clear();
    209                         cloneAll( oldType->parameters, newType->parameters );
    210                 }
    211                 return newType;
    212         }
    213 
    214         /// Get the type-id type from a virtual type.
    215         StructInstType * getTypeIdType( const Type * type, const CodeLocation& errorLocation ) {
    216                 const StructInstType * typeInst = dynamic_cast<const StructInstType *>( type );
    217                 if ( nullptr == typeInst ) {
    218                         return nullptr;
    219                 }
    220                 StructInstType * tableInst =
    221                         followHeadPointerType( typeInst, "virtual_table", errorLocation );
    222                 if ( nullptr == tableInst ) {
    223                         return nullptr;
    224                 }
    225                 StructInstType * typeIdInst =
    226                         followHeadPointerType( tableInst, "__cfavir_typeid", errorLocation );
    227                 delete tableInst;
    228                 return typeIdInst;
     195                        fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl );
     196                        if ( fieldDecl && fieldDecl->name != "virtual_table" ) {
     197                                fieldDecl = nullptr;
     198                        }
     199                }
     200                if ( nullptr == fieldDecl ) {
     201                        castError( castExpr, "Virtual cast type must have a leading virtual_table field." );
     202                }
     203                const PointerType * fieldType = dynamic_cast<const PointerType *>( fieldDecl->type );
     204                if ( nullptr == fieldType ) {
     205                        castError( castExpr, "Virtual cast type virtual_table field is not a pointer." );
     206                }
     207                assert( fieldType->base );
     208                auto virtualStructType = dynamic_cast<const StructInstType *>( fieldType->base );
     209                assert( virtualStructType );
     210
     211                // Here is the type, but if it is polymorphic it will have lost information.
     212                // (Always a clone so that it may always be deleted.)
     213                StructInstType * virtualType = virtualStructType->clone();
     214                if ( ! structType->parameters.empty() ) {
     215                        deleteAll( virtualType->parameters );
     216                        virtualType->parameters.clear();
     217                        cloneAll( structType->parameters, virtualType->parameters );
     218                }
     219                return virtualType;
    229220        }
    230221
     
    237228                assert( pvt_decl );
    238229
    239                 const Type * base_type = getBaseType( castExpr->result );
    240                 if ( nullptr == base_type ) {
    241                         castError( castExpr, "Virtual cast target must be a pointer or reference type." );
    242                 }
    243                 const Type * type_id_type = getTypeIdType( base_type, castLocation( castExpr ) );
    244                 if ( nullptr == type_id_type ) {
    245                         castError( castExpr, "Ill formed virtual cast target type." );
    246                 }
    247                 ObjectDecl * type_id = indexer.lookup( type_id_type );
    248                 delete type_id_type;
    249                 if ( nullptr == type_id ) {
    250                         castError( castExpr, "Virtual cast does not target a virtual type." );
     230                const Type * vtable_type = getVirtualTableType( castExpr );
     231                ObjectDecl * table = indexer.lookup( vtable_type );
     232                if ( nullptr == table ) {
     233                        SemanticError( castLocation( castExpr ),
     234                                "Could not find virtual table instance." );
    251235                }
    252236
    253237                Expression * result = new CastExpr(
    254238                        new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), {
    255                                 cast_to_type_id( new AddressExpr( new VariableExpr( type_id ) ), 1 ),
    256                                 cast_to_type_id( castExpr->get_arg(), 2 ),
     239                                        new CastExpr(
     240                                                new AddressExpr( new VariableExpr( table ) ),
     241                                                pointer_to_pvt(1)
     242                                        ),
     243                                        new CastExpr(
     244                                                castExpr->get_arg(),
     245                                                pointer_to_pvt(2)
     246                                        )
    257247                        } ),
    258248                        castExpr->get_result()->clone()
     
    262252                castExpr->set_result( nullptr );
    263253                delete castExpr;
     254                delete vtable_type;
    264255                return result;
    265256        }
  • src/Virtual/Tables.cc

    rfe63ae6 r56c8b86  
    1010// Created On       : Mon Aug 31 11:11:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Apr  8 15:51:00 2021
    13 // Update Count     : 1
     12// Last Modified On : Tue Sep  3 14:56:00 2020
     13// Update Count     : 0
    1414//
    1515
     
    2222namespace Virtual {
    2323
    24 std::string typeIdType( std::string const & type_name ) {
    25         return "__cfatid_struct_" + type_name;
    26 }
    27 
    28 std::string typeIdName( std::string const & type_name ) {
    29         return "__cfatid_" + type_name;
    30 }
    31 
    32 static std::string typeIdTypeToInstance( std::string const & type_name ) {
    33         return typeIdName(type_name.substr(16));
    34 }
    35 
    3624std::string vtableTypeName( std::string const & name ) {
    3725        return name + "_vtable";
    38 }
    39 
    40 std::string baseTypeName( std::string const & vtable_type_name ) {
    41         return vtable_type_name.substr(0, vtable_type_name.size() - 7);
    4226}
    4327
     
    9781                                inits.push_back(
    9882                                                new SingleInit( new AddressExpr( new NameExpr( parentInstance ) ) ) );
    99                         } else if ( std::string( "__cfavir_typeid" ) == field->name ) {
    100                                 std::string const & baseType = baseTypeName( vtableType->name );
    101                                 std::string const & typeId = typeIdName( baseType );
    102                                 inits.push_back( new SingleInit( new AddressExpr( new NameExpr( typeId ) ) ) );
    10383                        } else if ( std::string( "size" ) == field->name ) {
    10484                                inits.push_back( new SingleInit( new SizeofExpr( objectType->clone() ) ) );
     
    167147}
    168148
    169 ObjectDecl * makeTypeIdForward() {
    170         return nullptr;
    171149}
    172 
    173 Attribute * linkonce( const std::string & subsection ) {
    174         const std::string section = ".gnu.linkonce." + subsection;
    175         return new Attribute( "section", {
    176                 new ConstantExpr( Constant::from_string( section ) ),
    177         } );
    178 }
    179 
    180 ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType ) {
    181         assert( typeIdType );
    182         StructInstType * type = typeIdType->clone();
    183         type->tq.is_const = true;
    184         std::string const & typeid_name = typeIdTypeToInstance( typeIdType->name );
    185         return new ObjectDecl(
    186                 typeid_name,
    187                 noStorageClasses,
    188                 LinkageSpec::Cforall,
    189                 /* bitfieldWidth */ nullptr,
    190                 type,
    191                 new ListInit( { new SingleInit(
    192                         new AddressExpr( new NameExpr( "__cfatid_exception_t" ) )
    193                         ) } ),
    194                 { linkonce( typeid_name ) },
    195                 noFuncSpecifiers
    196         );
    197 }
    198 
    199 }
  • src/Virtual/Tables.h

    rfe63ae6 r56c8b86  
    1010// Created On       : Mon Aug 31 11:07:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Apr  8 15:55:00 2021
    13 // Update Count     : 1
     12// Last Modified On : Tue Sep  1 14:29:00 2020
     13// Update Count     : 0
    1414//
    1515
     
    2222namespace Virtual {
    2323
    24 std::string typeIdType( std::string const & type_name );
    25 std::string typeIdName( std::string const & type_name );
    2624std::string vtableTypeName( std::string const & type_name );
    2725std::string instanceName( std::string const & vtable_name );
     
    5250 */
    5351
    54 ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType );
    55 /* Build an instance of the type-id from the type of the type-id.
    56  * TODO: Should take the parent type. Currently locked to the exception_t.
    57  */
    58 
    5952}
  • tests/exceptions/.expect/resume-threads.txt

    rfe63ae6 r56c8b86  
    66
    77catch-all
     8
     9throwing child exception
     10inner parent match
    811
    912caught yin as yin
  • tests/exceptions/.expect/resume.txt

    rfe63ae6 r56c8b86  
    66
    77catch-all
     8
     9throwing child exception
     10inner parent match
    811
    912caught yin as yin
  • tests/exceptions/.expect/terminate-threads.txt

    rfe63ae6 r56c8b86  
    55
    66catch-all
     7
     8throwing child exception
     9inner parent match
    710
    811caught yin as yin
  • tests/exceptions/.expect/terminate.txt

    rfe63ae6 r56c8b86  
    55
    66catch-all
     7
     8throwing child exception
     9inner parent match
    710
    811caught yin as yin
  • tests/exceptions/cancel/coroutine.cfa

    rfe63ae6 r56c8b86  
    44#include <exception.hfa>
    55
    6 EHM_EXCEPTION(internal_error)();
    7 EHM_VIRTUAL_TABLE(internal_error, internal_vt);
     6TRIVIAL_EXCEPTION(internal_error);
    87
    98coroutine WillCancel {};
     
    1514void main(WillCancel & wc) {
    1615        printf("1");
    17         cancel_stack((internal_error){&internal_vt});
     16        cancel_stack((internal_error){});
    1817        printf("!");
    1918}
     
    2524                resume(cancel);
    2625                printf("4");
    27         } catchResume (SomeCoroutineCancelled * error) {
     26        } catchResume (CoroutineCancelled(WillCancel) * error) {
    2827                printf("2");
    2928                if ((virtual internal_error *)error->the_exception) {
  • tests/exceptions/cancel/thread.cfa

    rfe63ae6 r56c8b86  
    44#include <exception.hfa>
    55
    6 EHM_EXCEPTION(internal_error)();
    7 EHM_VIRTUAL_TABLE(internal_error, internal_vt);
     6TRIVIAL_EXCEPTION(internal_error);
    87
    98thread WillCancel {};
     
    1514void main(WillCancel &) {
    1615        printf("1");
    17         cancel_stack((internal_error){&internal_vt});
     16        cancel_stack((internal_error){});
    1817        printf("!");
    1918}
     
    2625                join(cancel);
    2726                printf("4");
    28         } catchResume (SomeThreadCancelled * error) {
     27        } catchResume (ThreadCancelled(WillCancel) * error) {
    2928                printf("2");
    3029                if ((virtual internal_error *)error->the_exception) {
     
    4342                }
    4443                printf("4");
    45         } catchResume (SomeThreadCancelled * error) {
     44        } catchResume (ThreadCancelled(WillCancel) * error) {
    4645                printf("2");
    4746                if ((virtual internal_error *)error->the_exception) {
  • tests/exceptions/conditional.cfa

    rfe63ae6 r56c8b86  
    66#include <exception.hfa>
    77
    8 EHM_EXCEPTION(num_error)(
    9         int num;
     8VTABLE_DECLARATION(num_error)(
     9        int (*code)(num_error *this);
    1010);
    1111
    12 EHM_VIRTUAL_TABLE(num_error, num_error_vt);
     12struct num_error {
     13        VTABLE_FIELD(num_error);
     14    char * msg;
     15    int num;
     16};
     17
     18const char * num_error_msg(num_error * this) {
     19    if ( ! this->msg ) {
     20        static const char * base = "Num Error with code: X";
     21        this->msg = (char *)malloc(22);
     22        for (int i = 0 ; (this->msg[i] = base[i]) ; ++i);
     23    }
     24    this->msg[21] = '0' + this->num;
     25    return this->msg;
     26}
     27void ?{}(num_error & this, int num) {
     28        VTABLE_INIT(this, num_error);
     29    this.msg = 0;
     30    this.num = num;
     31}
     32void ?{}(num_error & this, num_error & other) {
     33    this.virtual_table = other.virtual_table;
     34    this.msg = 0;
     35    this.num = other.num;
     36}
     37void ^?{}(num_error & this) {
     38    if( this.msg ) free( this.msg );
     39}
     40int num_error_code( num_error * this ) {
     41    return this->num;
     42}
     43
     44VTABLE_INSTANCE(num_error)(
     45        num_error_msg,
     46        num_error_code,
     47);
    1348
    1449void caught_num_error(int expect, num_error * actual) {
     
    1752
    1853int main(int argc, char * argv[]) {
    19         num_error exc = {&num_error_vt, 2};
     54        num_error exc = 2;
    2055
    2156        try {
    2257                throw exc;
    23         } catch (num_error * error ; 3 == error->num ) {
     58        } catch (num_error * error ; 3 == error->virtual_table->code( error )) {
    2459                caught_num_error(3, error);
    25         } catch (num_error * error ; 2 == error->num ) {
     60        } catch (num_error * error ; 2 == error->virtual_table->code( error )) {
    2661                caught_num_error(2, error);
    2762        }
     
    2964        try {
    3065                throwResume exc;
    31         } catchResume (num_error * error ; 3 == error->num ) {
     66        } catchResume (num_error * error ; 3 == error->virtual_table->code( error )) {
    3267                caught_num_error(3, error);
    33         } catchResume (num_error * error ; 2 == error->num ) {
     68        } catchResume (num_error * error ; 2 == error->virtual_table->code( error )) {
    3469                caught_num_error(2, error);
    3570        }
  • tests/exceptions/data-except.cfa

    rfe63ae6 r56c8b86  
    33#include <exception.hfa>
    44
    5 EHM_EXCEPTION(paired)(
     5DATA_EXCEPTION(paired)(
    66        int first;
    77        int second;
    88);
    99
    10 EHM_VIRTUAL_TABLE(paired, paired_vt);
     10void ?{}(paired & this, int first, int second) {
     11        VTABLE_INIT(this, paired);
     12        this.first = first;
     13        this.second = second;
     14}
    1115
    12 const char * virtual_msg(paired * this) {
    13         return this->virtual_table->msg(this);
     16const char * paired_msg(paired * this) {
     17        return "paired";
     18}
     19
     20VTABLE_INSTANCE(paired)(paired_msg);
     21
     22void throwPaired(int first, int second) {
     23        paired exc = {first, second};
    1424}
    1525
    1626int main(int argc, char * argv[]) {
    17         paired except = {&paired_vt, 3, 13};
     27        paired except = {3, 13};
    1828
    1929        try {
    2030                throw except;
    2131        } catch (paired * exc) {
    22                 printf("%s(%d, %d)\n", virtual_msg(exc), exc->first, exc->second);
     32                printf("%s(%d, %d)\n", paired_msg(exc), exc->first, exc->second);
    2333                ++exc->first;
    2434        }
    2535
    26         printf("%s(%d, %d)\n", virtual_msg(&except), except.first, except.second);
     36        printf("%s(%d, %d)\n", paired_msg(&except), except.first, except.second);
    2737
    2838        try {
    2939                throwResume except;
    3040        } catchResume (paired * exc) {
    31                 printf("%s(%d, %d)\n", virtual_msg(exc), exc->first, exc->second);
     41                printf("%s(%d, %d)\n", paired_msg(exc), exc->first, exc->second);
    3242                ++exc->first;
    3343        }
    3444
    35         printf("%s(%d, %d)\n", virtual_msg(&except), except.first, except.second);
     45        printf("%s(%d, %d)\n", paired_msg(&except), except.first, except.second);
    3646}
  • tests/exceptions/defaults.cfa

    rfe63ae6 r56c8b86  
    44#include <exception.hfa>
    55
    6 EHM_EXCEPTION(log_message)(
     6DATA_EXCEPTION(log_message)(
    77        char * msg;
    88);
    99
    10 _EHM_DEFINE_COPY(log_message, )
    11 const char * msg(log_message * this) {
     10void ?{}(log_message & this, char * msg) {
     11        VTABLE_INIT(this, log_message);
     12        this.msg = msg;
     13}
     14
     15const char * get_log_message(log_message * this) {
    1216        return this->msg;
    1317}
    14 _EHM_VIRTUAL_TABLE(log_message, , log_vt);
     18
     19VTABLE_INSTANCE(log_message)(get_log_message);
    1520
    1621// Logging messages don't have to be handled.
     
    2328        // We can catch log:
    2429        try {
    25                 throwResume (log_message){&log_vt, "Should be printed.\n"};
     30                throwResume (log_message){"Should be printed.\n"};
    2631        } catchResume (log_message * this) {
    2732                printf("%s", this->virtual_table->msg(this));
    2833        }
    2934        // But we don't have to:
    30         throwResume (log_message){&log_vt, "Should not be printed.\n"};
     35        throwResume (log_message){"Should not be printed.\n"};
    3136}
    3237
    3338// I don't have a good use case for doing the same with termination.
    34 EHM_EXCEPTION(jump)();
     39TRIVIAL_EXCEPTION(jump);
    3540void defaultTerminationHandler(jump &) {
    3641        printf("jump default handler.\n");
    3742}
    3843
    39 EHM_VIRTUAL_TABLE(jump, jump_vt);
    40 
    4144void jump_test(void) {
    4245        try {
    43                 throw (jump){&jump_vt};
     46                throw (jump){};
    4447        } catch (jump * this) {
    4548                printf("jump catch handler.\n");
    4649        }
    47         throw (jump){&jump_vt};
     50        throw (jump){};
    4851}
    4952
    50 EHM_EXCEPTION(first)();
    51 EHM_VIRTUAL_TABLE(first, first_vt);
    52 
    53 EHM_EXCEPTION(unhandled_exception)();
    54 EHM_VIRTUAL_TABLE(unhandled_exception, unhandled_vt);
     53TRIVIAL_EXCEPTION(first);
     54TRIVIAL_EXCEPTION(unhandled_exception);
    5555
    5656void unhandled_test(void) {
    5757        forall(T &, V & | is_exception(T, V))
    5858        void defaultTerminationHandler(T &) {
    59                 throw (unhandled_exception){&unhandled_vt};
     59                throw (unhandled_exception){};
    6060        }
    6161        void defaultTerminationHandler(unhandled_exception &) {
     
    6363        }
    6464        try {
    65                 throw (first){&first_vt};
     65                throw (first){};
    6666        } catch (unhandled_exception * t) {
    6767                printf("Catch unhandled_exception.\n");
     
    6969}
    7070
    71 EHM_EXCEPTION(second)();
    72 EHM_VIRTUAL_TABLE(second, second_vt);
     71TRIVIAL_EXCEPTION(second);
    7372
    7473void cross_test(void) {
    7574        void defaultTerminationHandler(first &) {
    7675                printf("cross terminate default\n");
    77                 throw (second){&second_vt};
     76                throw (second){};
    7877        }
    7978        void defaultResumptionHandler(first &) {
    8079                printf("cross resume default\n");
    81                 throwResume (second){&second_vt};
     80                throwResume (second){};
    8281        }
    8382        try {
    8483                printf("cross terminate throw\n");
    85                 throw (first){&first_vt};
     84                throw (first){};
    8685        } catch (second *) {
    8786                printf("cross terminate catch\n");
     
    8988        try {
    9089                printf("cross resume throw\n");
    91                 throwResume (first){&first_vt};
     90                throwResume (first){};
    9291        } catchResume (second *) {
    9392                printf("cross resume catch\n");
  • tests/exceptions/finally.cfa

    rfe63ae6 r56c8b86  
    44#include "except-io.hfa"
    55
    6 EHM_EXCEPTION(myth)();
    7 
    8 EHM_VIRTUAL_TABLE(myth, myth_vt);
     6TRIVIAL_EXCEPTION(myth);
    97
    108int main(int argc, char * argv[]) {
    11         myth exc = {&myth_vt};
     9        myth exc;
    1210
    1311        try {
  • tests/exceptions/interact.cfa

    rfe63ae6 r56c8b86  
    44#include "except-io.hfa"
    55
    6 EHM_EXCEPTION(star)();
    7 EHM_EXCEPTION(moon)();
    8 
    9 EHM_VIRTUAL_TABLE(star, star_vt);
    10 EHM_VIRTUAL_TABLE(moon, moon_vt);
     6TRIVIAL_EXCEPTION(star);
     7TRIVIAL_EXCEPTION(moon);
    118
    129int main(int argc, char * argv[]) {
    1310        // Resume falls back to terminate.
    1411        try {
    15                 throwResume (star){&star_vt};
     12                throwResume (star){};
    1613        } catch (star *) {
    1714                printf("caught as termination\n");
     
    2017        try {
    2118                loud_region a = "try block with resume throw";
    22                 throwResume (star){&star_vt};
     19                throwResume (star){};
    2320        } catch (star *) {
    2421                printf("caught as termination\n");
     
    3229        try {
    3330                try {
    34                         throw (star){&star_vt};
     31                        throw (star){};
    3532                } catchResume (star *) {
    3633                        printf("resume catch on terminate\n");
     
    4643        try {
    4744                try {
    48                         throwResume (star){&star_vt};
     45                        throwResume (star){};
    4946                } catch (star *) {
    5047                        printf("terminate catch on resume\n");
     
    6158                try {
    6259                        try {
    63                                 throw (star){&star_vt};
     60                                throw (star){};
    6461                        } catchResume (star *) {
    6562                                printf("inner resume catch (error)\n");
     
    7875                try {
    7976                        try {
    80                                 throwResume (star){&star_vt};
     77                                throwResume (star){};
    8178                        } catch (star *) {
    8279                                printf("inner termination catch\n");
     
    9794                                try {
    9895                                        printf("throwing resume moon\n");
    99                                         throwResume (moon){&moon_vt};
     96                                        throwResume (moon){};
    10097                                } catch (star *) {
    10198                                        printf("termination catch\n");
    10299                                }
    103100                                printf("throwing resume star\n");
    104                                 throwResume (star){&star_vt};
     101                                throwResume (star){};
    105102                        } catchResume (star *) {
    106103                                printf("resumption star catch\n");
     
    108105                } catchResume (moon *) {
    109106                        printf("resumption moon catch, will terminate\n");
    110                         throw (star){&star_vt};
     107                        throw (star){};
    111108                }
    112109        } catchResume (star *) {
  • tests/exceptions/polymorphic.cfa

    rfe63ae6 r56c8b86  
    33#include <exception.hfa>
    44
    5 EHM_FORALL_EXCEPTION(proxy, (T&), (T))();
     5FORALL_TRIVIAL_EXCEPTION(proxy, (T), (T));
     6FORALL_TRIVIAL_INSTANCE(proxy, (U), (U))
    67
    7 EHM_FORALL_VIRTUAL_TABLE(proxy, (int), proxy_int);
    8 EHM_FORALL_VIRTUAL_TABLE(proxy, (char), proxy_char);
     8const char * msg(proxy(int) * this) { return "proxy(int)"; }
     9const char * msg(proxy(char) * this) { return "proxy(char)"; }
     10POLY_VTABLE_INSTANCE(proxy, int)(msg);
     11POLY_VTABLE_INSTANCE(proxy, char)(msg);
    912
    1013void proxy_test(void) {
    11         proxy(int) an_int = {&proxy_int};
    12         proxy(char) a_char = {&proxy_char};
    13 
    1414    try {
    15                 throw an_int;
     15                throw (proxy(int)){};
    1616        } catch (proxy(int) *) {
    1717                printf("terminate catch\n");
     
    1919
    2020        try {
    21                 throwResume a_char;
     21                throwResume (proxy(char)){};
    2222        } catchResume (proxy(char) *) {
    2323                printf("resume catch\n");
     
    2525
    2626        try {
    27                 throw a_char;
     27                throw (proxy(char)){};
    2828        } catch (proxy(int) *) {
    2929                printf("caught proxy(int)\n");
     
    3333}
    3434
    35 EHM_FORALL_EXCEPTION(cell, (T), (T))(
     35FORALL_DATA_EXCEPTION(cell, (T), (T))(
    3636        T data;
    3737);
    3838
    39 EHM_FORALL_VIRTUAL_TABLE(cell, (int), int_cell);
    40 EHM_FORALL_VIRTUAL_TABLE(cell, (char), char_cell);
    41 EHM_FORALL_VIRTUAL_TABLE(cell, (bool), bool_cell);
     39FORALL_DATA_INSTANCE(cell, (T), (T))
     40
     41const char * msg(cell(int) * this) { return "cell(int)"; }
     42const char * msg(cell(char) * this) { return "cell(char)"; }
     43const char * msg(cell(bool) * this) { return "cell(bool)"; }
     44POLY_VTABLE_INSTANCE(cell, int)(msg);
     45POLY_VTABLE_INSTANCE(cell, char)(msg);
     46POLY_VTABLE_INSTANCE(cell, bool)(msg);
    4247
    4348void cell_test(void) {
    4449        try {
    45                 cell(int) except = {&int_cell, -7};
     50                cell(int) except;
     51                except.data = -7;
    4652                throw except;
    4753        } catch (cell(int) * error) {
     
    5056
    5157        try {
    52                 cell(bool) ball = {&bool_cell, false};
     58                cell(bool) ball;
     59                ball.data = false;
    5360                throwResume ball;
    5461                printf("%i\n", ball.data);
  • tests/exceptions/resume.cfa

    rfe63ae6 r56c8b86  
    44#include "except-io.hfa"
    55
    6 EHM_EXCEPTION(yin)();
    7 EHM_EXCEPTION(yang)();
    8 EHM_EXCEPTION(zen)();
    9 
    10 EHM_VIRTUAL_TABLE(yin, yin_vt);
    11 EHM_VIRTUAL_TABLE(yang, yang_vt);
    12 EHM_VIRTUAL_TABLE(zen, zen_vt);
     6TRIVIAL_EXCEPTION(yin);
     7TRIVIAL_EXCEPTION(yang);
     8TRIVIAL_EXCEPTION(zen);
     9TRIVIAL_EXCEPTION(moment_of, zen);
    1310
    1411void in_void(void);
    1512
    1613int main(int argc, char * argv[]) {
    17         yin a_yin = {&yin_vt};
    18         yang a_yang = {&yang_vt};
    19         zen a_zen = {&zen_vt};
    20 
    2114        // The simple throw catchResume test.
    2215        try {
    2316                loud_exit a = "simple try clause";
    2417                printf("simple throw\n");
    25                 throwResume a_zen;
     18                throwResume (zen){};
    2619                printf("end of try clause\n");
    2720        } catchResume (zen * error) {
     
    3326        // Throw catch-all test.
    3427        try {
    35                 throwResume a_zen;
     28                throwResume (zen){};
    3629        } catchResume (exception_t * error) {
    3730                printf("catch-all\n");
     31        }
     32        printf("\n");
     33
     34        // Catch a parent of the given exception.
     35        try {
     36                printf("throwing child exception\n");
     37                throwResume (moment_of){};
     38        } catchResume (zen *) {
     39                printf("inner parent match\n");
     40        } catchResume (moment_of *) {
     41                printf("outer exact match\n");
    3842        }
    3943        printf("\n");
     
    4246        try {
    4347                try {
    44                         throwResume a_yin;
     48                        throwResume (yin){};
    4549                } catchResume (zen *) {
    4650                        printf("caught yin as zen\n");
     
    5862                        loud_exit a = "rethrow inner try";
    5963                        printf("rethrow inner try\n");
    60                         throwResume a_zen;
     64                        throwResume (zen){};
    6165                } catchResume (zen *) {
    6266                        loud_exit a = "rethrowing catch clause";
     
    7377        try {
    7478                try {
    75                         throwResume a_yin;
     79                        throwResume (yin){};
    7680                } catchResume (yin *) {
    7781                        printf("caught yin, will throw yang\n");
    78                         throwResume a_yang;
     82                        throwResume (yang){};
    7983                } catchResume (yang *) {
    8084                        printf("caught exception from same try\n");
     
    8993                try {
    9094                        printf("throwing first exception\n");
    91                         throwResume a_yin;
     95                        throwResume (yin){};
    9296                } catchResume (yin *) {
    9397                        printf("caught first exception\n");
    9498                        try {
    9599                                printf("throwing second exception\n");
    96                                 throwResume a_yang;
     100                                throwResume (yang){};
    97101                        } catchResume (yang *) {
    98102                                printf("caught second exception\n");
     
    110114        try {
    111115                try {
    112                         throwResume a_zen;
    113                         throwResume a_zen;
     116                        throwResume (zen){};
     117                        throwResume (zen){};
    114118                } catchResume (zen *) {
    115119                        printf("inner catch\n");
    116120                }
    117                 throwResume a_zen;
     121                throwResume (zen){};
    118122        } catchResume (zen *) {
    119123                printf("outer catch\n");
     
    126130// Do a throw and rethrow in a void function.
    127131void in_void(void) {
    128     zen a_zen = {&zen_vt};
    129132        try {
    130133                try {
    131134                        printf("throw\n");
    132                         throwResume a_zen;
     135                        throwResume (zen){};
    133136                } catchResume (zen *) {
    134137                        printf("rethrow\n");
  • tests/exceptions/terminate.cfa

    rfe63ae6 r56c8b86  
    44#include "except-io.hfa"
    55
    6 EHM_EXCEPTION(yin)();
    7 EHM_EXCEPTION(yang)();
    8 EHM_EXCEPTION(zen)();
    9 
    10 EHM_VIRTUAL_TABLE(yin, yin_vt);
    11 EHM_VIRTUAL_TABLE(yang, yang_vt);
    12 EHM_VIRTUAL_TABLE(zen, zen_vt);
     6TRIVIAL_EXCEPTION(yin);
     7TRIVIAL_EXCEPTION(yang);
     8TRIVIAL_EXCEPTION(zen);
     9TRIVIAL_EXCEPTION(moment_of, zen);
    1310
    1411void in_void(void);
    1512
    1613int main(int argc, char * argv[]) {
    17         yin a_yin = {&yin_vt};
    18         yang a_yang = {&yang_vt};
    19         zen a_zen = {&zen_vt};
    20 
    2114        // The simple throw catch test.
    2215        try {
    2316                loud_exit a = "simple try clause";
    2417                printf("simple throw\n");
    25                 throw a_zen;
     18                throw (zen){};
    2619                printf("end of try clause\n");
    2720        } catch (zen * error) {
     
    3326        // Throw catch-all test.
    3427        try {
    35                 throw a_zen;
     28                throw (zen){};
    3629        } catch (exception_t * error) {
    3730                printf("catch-all\n");
     31        }
     32        printf("\n");
     33
     34        // Catch a parent of the given exception.
     35        try {
     36                printf("throwing child exception\n");
     37                throw (moment_of){};
     38        } catch (zen *) {
     39                printf("inner parent match\n");
     40        } catch (moment_of *) {
     41                printf("outer exact match\n");
    3842        }
    3943        printf("\n");
     
    4246        try {
    4347                try {
    44                         throw a_yin;
     48                        throw (yin){};
    4549                } catch (zen *) {
    4650                        printf("caught yin as zen\n");
     
    5862                        loud_exit a = "rethrow inner try";
    5963                        printf("rethrow inner try\n");
    60                         throw a_zen;
     64                        throw (zen){};
    6165                } catch (zen *) {
    6266                        loud_exit a = "rethrowing catch clause";
     
    7377        try {
    7478                try {
    75                         throw a_yin;
     79                        throw (yin){};
    7680                } catch (yin *) {
    7781                        printf("caught yin, will throw yang\n");
    78                         throw a_yang;
     82                        throw (yang){};
    7983                } catch (yang *) {
    8084                        printf("caught exception from same try\n");
     
    8993                try {
    9094                        printf("throwing first exception\n");
    91                         throw a_yin;
     95                        throw (yin){};
    9296                } catch (yin *) {
    9397                        printf("caught first exception\n");
    9498                        try {
    9599                                printf("throwing second exception\n");
    96                                 throw a_yang;
     100                                throw (yang){};
    97101                        } catch (yang *) {
    98102                                printf("caught second exception\n");
     
    110114        try {
    111115                try {
    112                         throw a_zen;
    113                         throw a_zen;
     116                        throw (zen){};
     117                        throw (zen){};
    114118                } catch (zen *) {
    115119                        printf("inner catch\n");
    116120                }
    117                 throw a_zen;
     121                throw (zen){};
    118122        } catch (zen *) {
    119123                printf("outer catch\n");
     
    126130// Do a throw and rethrow in a void function.
    127131void in_void(void) {
    128         zen a_zen = {&zen_vt};
    129132        try {
    130133                try {
    131134                        printf("throw\n");
    132                         throw a_zen;
     135                        throw (zen){};
    133136                } catch (zen *) {
    134137                        printf("rethrow\n");
  • tests/exceptions/trash.cfa

    rfe63ae6 r56c8b86  
    33#include <exception.hfa>
    44
    5 EHM_EXCEPTION(yin)();
    6 EHM_EXCEPTION(yang)();
    7 
    8 EHM_VIRTUAL_TABLE(yin, yin_vt);
    9 EHM_VIRTUAL_TABLE(yang, yang_vt);
     5TRIVIAL_EXCEPTION(yin);
     6TRIVIAL_EXCEPTION(yang);
    107
    118int main(int argc, char * argv[]) {
    129        try {
    1310                try {
    14                         throw (yin){&yin_vt};
     11                        throw (yin){};
    1512                } finally {
    1613                        try {
    17                                 throw (yang){&yang_vt};
     14                                throw (yang){};
    1815                        } catch (yin *) {
    1916                                printf("inner yin\n");
  • tests/exceptions/type-check.cfa

    rfe63ae6 r56c8b86  
    33#include <exception.hfa>
    44
    5 EHM_EXCEPTION(truth)();
     5TRIVIAL_EXCEPTION(truth);
    66
    77int main(int argc, char * argv[]) {
  • tests/exceptions/virtual-cast.cfa

    rfe63ae6 r56c8b86  
    1212#include <assert.h>
    1313
    14 
    15 
    16 // Hand defined alpha virtual type:
    17 struct __cfatid_struct_alpha {
    18         __cfa__parent_vtable const * parent;
    19 };
    20 
    21 __attribute__(( section(".gnu.linkonce.__cfatid_alpha") ))
    22 struct __cfatid_struct_alpha __cfatid_alpha = {
    23         (__cfa__parent_vtable *)0,
    24 };
    25 
    2614struct alpha_vtable {
    27         struct __cfatid_struct_alpha const * const __cfavir_typeid;
     15        alpha_vtable const * const parent;
    2816        char (*code)(void);
    2917};
     
    3927
    4028
    41 // Hand defined beta virtual type:
    42 struct __cfatid_struct_beta {
    43         __cfatid_struct_alpha const * parent;
    44 };
    45 
    46 __attribute__(( section(".gnu.linkonce.__cfatid_beta") ))
    47 struct __cfatid_struct_beta __cfatid_beta = {
    48         &__cfatid_alpha,
    49 };
    50 
    5129struct beta_vtable {
    52         struct __cfatid_struct_beta const * const __cfavir_typeid;
     30        alpha_vtable const * const parent;
    5331        char (*code)(void);
    5432};
     
    6442
    6543
    66 // Hand defined gamma virtual type:
    67 struct __cfatid_struct_gamma {
    68         __cfatid_struct_beta const * parent;
    69 };
    70 
    71 __attribute__(( section(".gnu.linkonce.__cfatid_gamma") ))
    72 struct __cfatid_struct_gamma __cfatid_gamma = {
    73         &__cfatid_beta,
    74 };
    75 
    7644struct gamma_vtable {
    77         struct __cfatid_struct_gamma const * const __cfavir_typeid;
     45        beta_vtable const * const parent;
    7846        char (*code)(void);
    7947};
     
    8957
    9058extern "C" {
    91         alpha_vtable _alpha_vtable_instance = { &__cfatid_alpha, ret_a };
    92         beta_vtable _beta_vtable_instance = { &__cfatid_beta, ret_b };
    93         gamma_vtable _gamma_vtable_instance = { &__cfatid_gamma, ret_g };
     59        alpha_vtable _alpha_vtable_instance = { 0, ret_a };
     60        beta_vtable _beta_vtable_instance = { &_alpha_vtable_instance, ret_b };
     61        gamma_vtable _gamma_vtable_instance = { &_beta_vtable_instance, ret_g };
    9462}
    9563
  • tests/exceptions/virtual-poly.cfa

    rfe63ae6 r56c8b86  
    88#include <assert.h>
    99
    10 
    11 struct __cfatid_struct_mono_base {
    12     __cfa__parent_vtable const * parent;
    13 };
    14 
    15 __attribute__(( section(".gnu.linkonce.__cfatid_mono_base") ))
    16 struct __cfatid_struct_mono_base __cfatid_mono_base = {
    17     (__cfa__parent_vtable *)0,
    18 };
    19 
    2010struct mono_base_vtable {
    21         __cfatid_struct_mono_base const * const __cfavir_typeid;
     11        mono_base_vtable const * const parent;
    2212};
    2313
     
    2717
    2818forall(T)
    29 struct __cfatid_struct_mono_child {
    30     __cfatid_struct_mono_base const * parent;
    31 };
    32 
    33 forall(T)
    3419struct mono_child_vtable {
    35         __cfatid_struct_mono_child(T) const * const __cfavir_typeid;
     20        mono_base_vtable const * const parent;
    3621};
    3722
     
    4126};
    4227
    43 __cfatid_struct_mono_child(int) __cfatid_mono_child @= {
    44         &__cfatid_mono_base,
    45 };
    46 
     28mono_base_vtable _mono_base_vtable_instance @= { 0 };
    4729mono_child_vtable(int) _mono_child_vtable_instance @= {
    48         &__cfatid_mono_child,
     30        &_mono_base_vtable_instance
    4931};
    5032
     
    5537}
    5638
    57 
    58 forall(U)
    59 struct __cfatid_struct_poly_base {
    60     __cfa__parent_vtable const * parent;
    61 };
    62 
    6339forall(U)
    6440struct poly_base_vtable {
    65         __cfatid_struct_poly_base(U) const * const __cfavir_typeid;
     41        poly_base_vtable(U) const * const parent;
    6642};
    6743
     
    7248
    7349forall(V)
    74 struct __cfatid_struct_poly_child {
    75     __cfatid_struct_poly_base(V) const * parent;
    76 };
    77 
    78 forall(V)
    7950struct poly_child_vtable {
    80         __cfatid_struct_poly_child(V) const * const __cfavir_typeid;
     51        poly_base_vtable(V) const * const parent;
    8152};
    8253
     
    8657};
    8758
    88 __cfatid_struct_poly_base(int) __cfatid_poly_base @= {
    89         (__cfa__parent_vtable *)0,
     59poly_base_vtable(int) _poly_base_vtable_instance @= { 0 };
     60poly_child_vtable(int) _poly_child_vtable_instance @= {
     61        &_poly_base_vtable_instance
    9062};
    91 __cfatid_struct_poly_child(int) __cfatid_poly_child = {
    92     &__cfatid_poly_base,
     63/* Resolver bug keeps me from adding these.
     64poly_base_vtable(char) _poly_base_vtable_instance @= { 0 };
     65poly_child_vtable(char) _poly_child_vtable_instance @= {
     66        &_poly_base_vtable_instance
    9367};
    94 poly_child_vtable(int) _poly_child_vtable_instance @= {
    95         &__cfatid_poly_child,
    96 };
     68*/
    9769
    9870void poly_poly_test() {
     
    10577        mono_poly_test();
    10678        poly_poly_test();
    107         printf( "done\n" );
     79        printf( "done\n" );                             // non-empty .expect file
    10880}
  • tests/linking/exception-nothreads.cfa

    rfe63ae6 r56c8b86  
    1717#include <exception.hfa>
    1818
    19 EHM_EXCEPTION(ping)();
    20 EHM_VIRTUAL_TABLE(ping, ping_vt);
     19TRIVIAL_EXCEPTION(ping);
    2120
    2221int main(void) {
    2322        try {
    24                 throwResume (ping){&ping_vt};
     23                throwResume (ping){};
    2524        } catchResume (ping *) {
    2625                printf("%s threads\n", threading_enabled() ? "with" : "no");
  • tests/linking/exception-withthreads.cfa

    rfe63ae6 r56c8b86  
    1818#include "../exceptions/with-threads.hfa"
    1919
    20 EHM_EXCEPTION(ping)();
    21 EHM_VIRTUAL_TABLE(ping, ping_vt);
     20TRIVIAL_EXCEPTION(ping);
    2221
    2322int main(void) {
    2423        try {
    25                 throwResume (ping){&ping_vt};
     24                throwResume (ping){};
    2625        } catchResume (ping *) {
    2726                printf("%s threads\n", threading_enabled() ? "with" : "no");
  • tests/quasiKeyword.cfa

    rfe63ae6 r56c8b86  
    1414#include <exception.hfa>
    1515
    16 EHM_EXCEPTION( E )();
     16TRIVIAL_EXCEPTION( E );
    1717
    1818void catch( int i ) {}
Note: See TracChangeset for help on using the changeset viewer.