Changeset 21b0a23


Ignore:
Timestamp:
Aug 4, 2020, 4:25:18 PM (15 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
arm-eh, jacob/cs343-translation, master, new-ast, new-ast-unique-expr
Children:
53ee27e
Parents:
f277633
Message:

Added polymophic exception macros. It adds a number of macros to help generate polymorphic exception code and a test for it.

Files:
2 added
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/exception.hfa

    rf277633 r21b0a23  
    1010// Created On       : Thu Apr  7 10:25:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue May 19 14:17:00 2020
    13 // Update Count     : 2
     12// Last Modified On : Tue Aug  4 16:22:00 2020
     13// Update Count     : 3
    1414//
    1515
     
    1818// -----------------------------------------------------------------------------------------------
    1919
    20 // All internals helper macros begin with an underscore.
    21 #define _CLOSE(...) __VA_ARGS__ }
    22 #define _GLUE2(left, right) left##right
    23 #define _GLUE3(left, middle, right) left##middle##right
    24 #define _EXC_DISPATCH(to, ...) to(__VA_ARGS__,__cfaehm_base_exception_t,)
    25 
    26 // FWD_TRIVIAL_EXCEPTION(exception_name);
     20// TRIVIAL_EXCEPTION_DECLARATION(exception_name);
    2721// Declare a trivial exception, one that adds no fields or features.
    2822// This will make the exception visible and may go in a .hfa or .cfa file.
    29 #define FWD_TRIVIAL_EXCEPTION(...) _EXC_DISPATCH(_FWD_TRIVIAL_EXCEPTION, __VA_ARGS__)
    30 // INST_TRIVIAL_EXCEPTION(exception_name);
     23#define TRIVIAL_EXCEPTION_DECLARATION(...) \
     24        _EXC_DISPATCH(_TRIVIAL_EXCEPTION_DECLARATION, __VA_ARGS__)
     25
     26// TRIVIAL_EXCEPTION_INSTANCE(exception_name);
    3127// Create the trival exception. This must be used exactly once and should be used in a .cfa file,
    3228// as it creates the unique instance of the virtual table.
    33 #define INST_TRIVIAL_EXCEPTION(...) _EXC_DISPATCH(_INST_TRIVIAL_EXCEPTION, __VA_ARGS__)
     29#define TRIVIAL_EXCEPTION_INSTANCE(...) _EXC_DISPATCH(_TRIVIAL_EXCEPTION_INSTANCE, __VA_ARGS__)
     30
    3431// TRIVIAL_EXCEPTION(exception_name[, parent_name]);
    3532// Does both of the above, a short hand if the exception is only used in one .cfa file.
     
    3734// base exception. This feature may be removed or changed.
    3835#define TRIVIAL_EXCEPTION(...) \
    39         _EXC_DISPATCH(_FWD_TRIVIAL_EXCEPTION, __VA_ARGS__); \
    40         _EXC_DISPATCH(_INST_TRIVIAL_EXCEPTION, __VA_ARGS__)
    41 #define _FWD_TRIVIAL_EXCEPTION(exception_name, parent_name, ...) \
     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        void mark_exception(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); }
     127
     128// All internal helper macros begin with an underscore.
     129#define _CLOSE(...) __VA_ARGS__ }
     130#define _GLUE2(left, right) left##right
     131#define _GLUE3(left, middle, right) left##middle##right
     132#define _EXC_DISPATCH(to, ...) to(__VA_ARGS__,__cfaehm_base_exception_t,)
     133#define _UNPACK(...) __VA_ARGS__
     134
     135#define _TRIVIAL_EXCEPTION_DECLARATION(exception_name, parent_name, ...) \
    42136        _VTABLE_DECLARATION(exception_name, parent_name)(); \
    43137        struct exception_name { \
     
    46140        void ?{}(exception_name & this); \
    47141        const char * _GLUE2(exception_name,_msg)(exception_name * this)
    48 #define _INST_TRIVIAL_EXCEPTION(exception_name, parent_name, ...) \
     142
     143#define _TRIVIAL_EXCEPTION_INSTANCE(exception_name, parent_name, ...) \
    49144        void ?{}(exception_name & this) { \
    50145                VTABLE_INIT(this, exception_name); \
     
    55150        _VTABLE_INSTANCE(exception_name, parent_name,)(_GLUE2(exception_name,_msg))
    56151
    57 // DATA_EXCEPTION(exception_name)(fields...);
    58 // Forward declare an exception that adds fields but no features. The added fields go in the
    59 // second argument list. The virtual table instance must be provided later (see VTABLE_INSTANCE).
    60 #define DATA_EXCEPTION(...) _EXC_DISPATCH(_DATA_EXCEPTION, __VA_ARGS__)
     152#define _FORALL_TRIVIAL_EXCEPTION(exception_name, parent_name, assertions, \
     153                parameters, parent_parameters) \
     154        _FORALL_VTABLE_DECLARATION(exception_name, parent_name, assertions, \
     155                parameters, parent_parameters)(); \
     156        forall assertions struct exception_name { \
     157                FORALL_VTABLE_FIELD(exception_name, parameters); \
     158        }; \
     159        _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters)
     160
     161#define _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) \
     162        forall(_UNPACK assertions | VTABLE_ASSERTION(exception_name, assertions, parameters) ) \
     163                /*| { VTABLE_TYPE(exception_name) parameters VTABLE_NAME(exception_name); } ) */ \
     164        void ?{}(exception_name parameters & this)
     165
     166#define _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters) \
     167        _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) { \
     168                VTABLE_INIT(this, exception_name); \
     169        }
     170
    61171#define _DATA_EXCEPTION(exception_name, parent_name, ...) \
    62172        _VTABLE_DECLARATION(exception_name, parent_name)(); \
    63         struct exception_name { VTABLE_FIELD(exception_name); _CLOSE
    64 
    65 // VTABLE_DECLARATION(exception_name)([new_features...]);
    66 // Declare a virtual table type for an exception with exception_name. You may also add features
    67 // (fields on the virtual table) by including them in the second list.
    68 #define VTABLE_DECLARATION(...) _EXC_DISPATCH(_VTABLE_DECLARATION, __VA_ARGS__)
     173        struct exception_name { \
     174                VTABLE_FIELD(exception_name); \
     175                _CLOSE
     176
     177#define _FORALL_DATA_EXCEPTION(exception_name, parent_name, \
     178                assertions, parameters, parent_parameters) \
     179        _FORALL_VTABLE_DECLARATION(exception_name, parent_name, \
     180                assertions, parameters, parent_parameters)(); \
     181        _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters); \
     182        forall assertions struct exception_name { \
     183                FORALL_VTABLE_FIELD(exception_name, parameters); \
     184                _CLOSE
     185
    69186#define _VTABLE_DECLARATION(exception_name, parent_name, ...) \
    70187        struct exception_name; \
     
    80197                _CLOSE
    81198
    82 // VTABLE_INSTANCE(exception_name)(msg [, others...]);
    83 // Create the instance of the virtual table. There must be exactly one instance of a virtual table
    84 // for each exception type. This fills in most of the fields of the virtual table (uses ?=? and
    85 // ^?{}) but you must provide the message function and any other fields added in the declaration.
    86 #define VTABLE_INSTANCE(...) _EXC_DISPATCH(_VTABLE_INSTANCE, __VA_ARGS__)
    87199#define _VTABLE_INSTANCE(exception_name, parent_name, ...) \
    88200        void mark_exception(exception_name *) {} \
     
    95207                _CLOSE
    96208
    97 // VTABLE_TYPE(exception_name) | VTABLE_NAME(exception_name)
    98 // Get the name of the vtable type or the name of the vtable instance for an exception type.
    99 #define VTABLE_TYPE(exception_name) struct _GLUE2(exception_name,_vtable)
    100 #define VTABLE_NAME(exception_name) _GLUE3(_,exception_name,_vtable_instance)
    101 
    102 // VTABLE_FIELD(exception_name);
    103 // The declaration of the virtual table field. Should be the first declaration in a virtual type.
    104 #define VTABLE_FIELD(exception_name) VTABLE_TYPE(exception_name) const * virtual_table
    105 
    106 // VTABLE_INIT(object_reference, exception_name);
    107 // Sets a virtual table field on an object to the virtual table instance for the type.
    108 #define VTABLE_INIT(this, exception_name) (this).virtual_table = &VTABLE_NAME(exception_name)
     209#define _FORALL_VTABLE_DECLARATION(exception_name, parent_name, assertions, \
     210                parameters, parent_parameters) \
     211        forall assertions struct exception_name; \
     212        forall assertions VTABLE_TYPE(exception_name) { \
     213                VTABLE_TYPE(parent_name) parent_parameters const * parent; \
     214                size_t size; \
     215                void (*copy)(exception_name parameters * this, exception_name parameters * other); \
     216                void (*free)(exception_name parameters & this); \
     217                const char * (*msg)(exception_name parameters * this); \
     218                _CLOSE
     219
     220#define _POLY_VTABLE_INSTANCE(exception_name, parent_name, ...) \
     221        void mark_exception(exception_name(__VA_ARGS__) *) {} \
     222        void _GLUE2(exception_name,_copy)( \
     223                        exception_name(__VA_ARGS__) * this, exception_name(__VA_ARGS__) * other) { \
     224                *this = *other; \
     225        } \
     226        VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name) @= { \
     227                &VTABLE_NAME(parent_name), sizeof(exception_name(__VA_ARGS__)), \
     228                _GLUE2(exception_name,_copy), ^?{}, \
     229                _CLOSE
Note: See TracChangeset for help on using the changeset viewer.