Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/exception.hfa

    r5456537 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 // EHM_DEFAULT_VTABLE(exception_name, (arguments))
    67 // Create a declaration for a (possibly polymorphic) default vtable.
    68 #define EHM_DEFAULT_VTABLE(exception_name, arguments) \
    69         _EHM_VTABLE_TYPE(exception_name) arguments & const _default_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); }
    70127
    71128// IS_EXCEPTION(exception_name [, (...parameters)])
     
    78135#define IS_TERMINATION_EXCEPTION(...) _IS_EXCEPTION(is_termination_exception, __VA_ARGS__, , ~)
    79136
    80 // Macros starting with a leading underscore are internal.
    81 
    82 // Create an exception type definition. must be tailing, can be polymorphic.
    83 #define _EHM_EXCEPTION_STRUCT(exception_name, forall_clause, parameters) \
    84         forall_clause struct exception_name { \
    85                 _EHM_VTABLE_TYPE(exception_name) parameters const * virtual_table; \
    86                 _CLOSE
    87 
    88 // Create a (possibly polymorphic) virtual table forward declaration.
    89 #define _EHM_EXTERN_VTABLE(exception_name, arguments, table_name) \
    90         extern const _EHM_VTABLE_TYPE(exception_name) arguments table_name
    91 
    92 // Create a (possibly polymorphic) virtual table definition.
    93 #define _EHM_VIRTUAL_TABLE(exception_type, arguments, table_name) \
    94         const _EHM_VTABLE_TYPE(exception_type) arguments table_name @= { \
    95                 .__cfavir_typeid : &_EHM_TYPE_ID_NAME(exception_type), \
    96                 .size : sizeof(struct exception_type arguments), \
    97                 .copy : copy, \
    98                 .^?{} : ^?{}, \
    99                 .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); \
    100178        }
    101179
    102 // Create a (possibly polymorphic) copy function from an assignment operator.
    103 #define _EHM_DEFINE_FORALL_COPY(exception_name, forall_clause, parameters) \
    104         forall_clause void copy(exception_name parameters * this, \
    105                         exception_name parameters * that) { \
    106                 *this = *that; \
    107         }
    108 
    109 #define _EHM_DEFINE_COPY(exception_name, arguments) \
    110         void copy(exception_name arguments * this, exception_name arguments * that) { \
    111                 *this = *that; \
    112         }
    113 
    114 // Create a (possibly polymorphic) msg function
    115 #define _EHM_DEFINE_FORALL_MSG(exception_name, forall_clause, parameters) \
    116         forall_clause const char * msg(exception_name parameters * this) { \
    117                 return #exception_name #parameters; \
    118         }
    119 
    120 #define _EHM_DEFINE_MSG(exception_name, arguments) \
    121         const char * msg(exception_name arguments * this) { \
    122                 return #exception_name #arguments; \
    123         }
    124 
    125 // Produces the C compatable name of the virtual table type for a virtual type.
    126 #define _EHM_VTABLE_TYPE(type_name) struct _GLUE2(type_name,_vtable)
    127 
    128 // Create the vtable type for exception name.
    129 #define _EHM_VIRTUAL_TABLE_STRUCT(exception_name, forall_clause, parameters) \
    130         forall_clause struct exception_name; \
    131         forall_clause _EHM_VTABLE_TYPE(exception_name) { \
    132                 _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; \
    133225                size_t size; \
    134226                void (*copy)(exception_name parameters * this, exception_name parameters * other); \
    135227                void (*^?{})(exception_name parameters & this); \
    136228                const char * (*msg)(exception_name parameters * this); \
    137         }
    138 
    139 // Define the function required to satify the trait for exceptions.
    140 #define _EHM_TRAIT_FUNCTION(exception_name, forall_clause, parameters) \
    141         forall_clause inline void mark_exception( \
    142                 exception_name parameters const &, \
    143                 _EHM_VTABLE_TYPE(exception_name) parameters const &) {} \
    144 
    145 #define __EHM_TRAIT_FUNCTION(exception_name, forall_clause, parameters) \
    146         forall_clause inline _EHM_VTABLE_TYPE(exception_name) parameters const & \
    147                         get_exception_vtable(exception_name parameters const & this) { \
    148                 /* This comes before the structure definition, but we know the offset. */ \
    149                 /* return (_EHM_VTABLE_TYPE(exception_name) parameters const &)this; */ \
    150                 assert(false); \
    151         }
    152 
    153 // Generates a new type-id structure. This is used to mangle the name of the
    154 // type-id instance so it also includes polymorphic information. Must be the
    155 // direct decendent of exception_t.
    156 // The second field is used to recover type information about the exception.
    157 #define _EHM_TYPE_ID_STRUCT(exception_name, forall_clause) \
    158         forall_clause _EHM_TYPE_ID_TYPE(exception_name) { \
    159                 __cfa__parent_vtable const * parent; \
    160         }
    161 
    162 // Generate a new type-id value.
    163 #define _EHM_TYPE_ID_VALUE(exception_name, arguments) \
    164         __attribute__(( section(".gnu.linkonce." "__cfatid_" #exception_name) )) \
    165         _EHM_TYPE_ID_TYPE(exception_name) arguments const \
    166                         _EHM_TYPE_ID_NAME(exception_name) = { \
    167                 &__cfatid_exception_t, \
    168         }
    169 
    170 // _EHM_TYPE_ID_STRUCT and _EHM_TYPE_ID_VALUE are the two that would need to
    171 // be updated to extend the hierarchy if we are still using macros when that
    172 // is added.
    173 
    174 // Produce the C compatable name of the type-id type for an exception type.
    175 #define _EHM_TYPE_ID_TYPE(exception_name) \
    176         struct _GLUE2(__cfatid_struct_, exception_name)
    177 
    178 // Produce the name of the instance of the type-id for an exception type.
    179 #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
    180245
    181246#define _IS_EXCEPTION(kind, exception_name, parameters, ...) \
    182         kind(exception_name parameters, _EHM_VTABLE_TYPE(exception_name) parameters)
    183 
    184 // Internal helper macros:
    185 #define _CLOSE(...) __VA_ARGS__ }
    186 #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.