Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/exception.hfa

    recfd758 r8fc9a5f  
    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)
Note: See TracChangeset for help on using the changeset viewer.