// // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // exception.hfa -- User facing tools for working with exceptions. // // Author : Andrew Beach // Created On : Thu Apr 7 10:25:00 2020 // Last Modified By : Andrew Beach // Last Modified On : Tue Aug 4 16:22:00 2020 // Update Count : 3 // // Everything below this line should be considered a patch while the exception // objects themselves are designed and created and should be removed in time. // ----------------------------------------------------------------------------------------------- // TRIVIAL_EXCEPTION_DECLARATION(exception_name); // Declare a trivial exception, one that adds no fields or features. // This will make the exception visible and may go in a .hfa or .cfa file. #define TRIVIAL_EXCEPTION_DECLARATION(...) \ _EXC_DISPATCH(_TRIVIAL_EXCEPTION_DECLARATION, __VA_ARGS__) // TRIVIAL_EXCEPTION_INSTANCE(exception_name); // Create the trival exception. This must be used exactly once and should be used in a .cfa file, // as it creates the unique instance of the virtual table. #define TRIVIAL_EXCEPTION_INSTANCE(...) _EXC_DISPATCH(_TRIVIAL_EXCEPTION_INSTANCE, __VA_ARGS__) // TRIVIAL_EXCEPTION(exception_name[, parent_name]); // Does both of the above, a short hand if the exception is only used in one .cfa file. // For legacy reasons this is the only one that official supports having a parent other than the // base exception. This feature may be removed or changed. #define TRIVIAL_EXCEPTION(...) \ _EXC_DISPATCH(_TRIVIAL_EXCEPTION_DECLARATION, __VA_ARGS__); \ _EXC_DISPATCH(_TRIVIAL_EXCEPTION_INSTANCE, __VA_ARGS__) // FORALL_TRIVIAL_EXCEPTION(exception_name, (assertions...), (parameters...)); // Forward declare a polymorphic but otherwise trivial exception type. You must provide the entire // assertion list (exactly what would go in the forall clause) and parameters list (only the // parameter names from the assertion list, same order and comma seperated). This should be // visible where ever use the exception. This just generates the polymorphic framework, see // POLY_VTABLE_DECLARATION to allow instantiations. #define FORALL_TRIVIAL_EXCEPTION(exception_name, assertions, parameters) \ _FORALL_TRIVIAL_EXCEPTION(exception_name, __cfaehm_base_exception_t, assertions, parameters, ) // FORALL_TRIVIAL_INSTANCE(exception_name, (assertions...), (parameters...)) // Create the forall trivial exception. The assertion list and parameters must match. // There must be exactly one use of this in a program for each exception type. This just // generates the polymorphic framework, see POLY_VTABLE_INSTANCE to allow instantiations. #define FORALL_TRIVIAL_INSTANCE(exception_name, assertions, parameters) \ _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters) // DATA_EXCEPTION(exception_name)(fields...); // Forward declare an exception that adds fields but no features. The added fields go in the // second argument list. The virtual table instance must be provided later (see VTABLE_INSTANCE). #define DATA_EXCEPTION(...) _EXC_DISPATCH(_DATA_EXCEPTION, __VA_ARGS__) // FORALL_DATA_EXCEPTION(exception_name, (assertions...), (parameters...))(fields...); // Define a polymorphic exception that adds fields but no additional features. The assertion list // and matching parameters must match. Then you can give the list of fields. This should be // visible where ever you use the exception. This just generates the polymorphic framework, see // POLY_VTABLE_DECLARATION to allow instantiations. #define FORALL_DATA_EXCEPTION(exception_name, assertions, parameters) \ _FORALL_DATA_EXCEPTION(exception_name, __cfaehm_base_exception_t, assertions, parameters, ) // FORALL_DATA_INSTANCE(exception_name, (assertions...), (parameters...)) // Create a polymorphic data exception. The assertion list and parameters must match. This should // appear once in each program. This just generates the polymorphic framework, see // POLY_VTABLE_INSTANCE to allow instantiations. #define FORALL_DATA_INSTANCE(exception_name, assertions, parameters) \ _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters) // VTABLE_DECLARATION(exception_name)([new_features...]); // Declare a virtual table type for an exception with exception_name. You may also add features // (fields on the virtual table) by including them in the second list. #define VTABLE_DECLARATION(...) _EXC_DISPATCH(_VTABLE_DECLARATION, __VA_ARGS__) // VTABLE_INSTANCE(exception_name)(msg [, others...]); // Create the instance of the virtual table. There must be exactly one instance of a virtual table // for each exception type. This fills in most of the fields of the virtual table (uses ?=? and // ^?{}) but you must provide the message function and any other fields added in the declaration. #define VTABLE_INSTANCE(...) _EXC_DISPATCH(_VTABLE_INSTANCE, __VA_ARGS__) // FORALL_VTABLE_DECLARATION(exception_name, (assertions...), (parameters...))([new_features...]); // Declare a polymorphic virtual table type for an exception with exception_name, the given // assertions and parameters. You may also add features (fields on the virtual table). This just // generates the polymorphic framework, see POLY_VTABLE_DECLARATION to allow instantiations. #define FORALL_VTABLE_DECLARATION(exception_name, assertions, parameters) \ _FORALL_VTABLE_DECLARATION(exception_name, __cfaehm_base_exception_t, assertions, parameters, ) // POLY_VTABLE_DECLARATION(exception_name, types...); // Declares that an instantiation for this exception exists for the given types. This should be // visible anywhere you use the instantiation of the exception is used. #define POLY_VTABLE_DECLARATION(exception_name, ...) \ VTABLE_TYPE(exception_name)(__VA_ARGS__) const & get_exception_vtable(exception_name(__VA_ARGS__) *); \ extern VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name) // POLY_VTABLE_INSTANCE(exception_name, types...)(msg [, others...]); // Creates an instantiation for the given exception for the given types. This should occur only // once in the entire program. You must fill in all features, message and any others given in the // initial declaration. #define POLY_VTABLE_INSTANCE(exception_name, ...) \ _POLY_VTABLE_INSTANCE(exception_name, __cfaehm_base_exception_t, __VA_ARGS__) // VTABLE_TYPE(exception_name) | VTABLE_NAME(exception_name) // Get the name of the vtable type or the name of the vtable instance for an exception type. #define VTABLE_TYPE(exception_name) struct _GLUE2(exception_name,_vtable) #define VTABLE_NAME(exception_name) _GLUE3(_,exception_name,_vtable_instance) // VTABLE_FIELD(exception_name); // FORALL_VTABLE_FIELD(exception_name, (parameters-or-types)); // The declaration of the virtual table field. Should be the first declaration in a virtual type. #define VTABLE_FIELD(exception_name) VTABLE_TYPE(exception_name) const * virtual_table #define FORALL_VTABLE_FIELD(exception_name, parameters) \ VTABLE_TYPE(exception_name) parameters const * virtual_table // VTABLE_INIT(object_reference, exception_name); // Sets a virtual table field on an object to the virtual table instance for the type. #define VTABLE_INIT(this, exception_name) (this).virtual_table = &VTABLE_NAME(exception_name) // VTABLE_ASSERTION(exception_name, (parameters...)) // The assertion that there is an instantiation of the vtable for the exception and types. #define VTABLE_ASSERTION(exception_name, parameters) \ { VTABLE_TYPE(exception_name) parameters VTABLE_NAME(exception_name); } // IS_EXCEPTION(exception_name [, (...parameters)]) // IS_RESUMPTION_EXCEPTION(exception_name [, (parameters...)]) // IS_TERMINATION_EXCEPTION(exception_name [, (parameters...)]) // Create an assertion that exception_name, possibly with the qualifing parameters, is the given // kind of exception with the standard vtable with the same parameters if applicable. #define IS_EXCEPTION(...) _IS_EXCEPTION(is_exception, __VA_ARGS__, , ~) #define IS_RESUMPTION_EXCEPTION(...) _IS_EXCEPTION(is_resumption_exception, __VA_ARGS__, , ~) #define IS_TERMINATION_EXCEPTION(...) _IS_EXCEPTION(is_termination_exception, __VA_ARGS__, , ~) // All internal helper macros begin with an underscore. #define _CLOSE(...) __VA_ARGS__ } #define _GLUE2(left, right) left##right #define _GLUE3(left, middle, right) left##middle##right #define _EXC_DISPATCH(to, ...) to(__VA_ARGS__,__cfaehm_base_exception_t,) #define _UNPACK(...) __VA_ARGS__ #define _TRIVIAL_EXCEPTION_DECLARATION(exception_name, parent_name, ...) \ _VTABLE_DECLARATION(exception_name, parent_name)(); \ struct exception_name { \ VTABLE_FIELD(exception_name); \ }; \ void ?{}(exception_name & this); \ const char * _GLUE2(exception_name,_msg)(exception_name * this) #define _TRIVIAL_EXCEPTION_INSTANCE(exception_name, parent_name, ...) \ void ?{}(exception_name & this) { \ VTABLE_INIT(this, exception_name); \ } \ const char * _GLUE2(exception_name,_msg)(exception_name * this) { \ return #exception_name; \ } \ _VTABLE_INSTANCE(exception_name, parent_name,)(_GLUE2(exception_name,_msg)) #define _FORALL_TRIVIAL_EXCEPTION(exception_name, parent_name, assertions, \ parameters, parent_parameters) \ _FORALL_VTABLE_DECLARATION(exception_name, parent_name, assertions, \ parameters, parent_parameters)(); \ forall assertions struct exception_name { \ FORALL_VTABLE_FIELD(exception_name, parameters); \ }; \ _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) #define _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) \ forall(_UNPACK assertions | \ is_exception(exception_name parameters, VTABLE_TYPE(exception_name) parameters)) \ void ?{}(exception_name parameters & this) #define _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters) \ _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) { \ (this).virtual_table = &get_exception_vtable(&this); \ } #define _DATA_EXCEPTION(exception_name, parent_name, ...) \ _VTABLE_DECLARATION(exception_name, parent_name)(); \ struct exception_name { \ VTABLE_FIELD(exception_name); \ _CLOSE #define _FORALL_DATA_EXCEPTION(exception_name, parent_name, \ assertions, parameters, parent_parameters) \ _FORALL_VTABLE_DECLARATION(exception_name, parent_name, \ assertions, parameters, parent_parameters)(); \ _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters); \ forall assertions struct exception_name { \ FORALL_VTABLE_FIELD(exception_name, parameters); \ _CLOSE #define _VTABLE_DECLARATION(exception_name, parent_name, ...) \ struct exception_name; \ VTABLE_TYPE(exception_name); \ VTABLE_TYPE(exception_name) const & get_exception_vtable(exception_name *); \ extern VTABLE_TYPE(exception_name) VTABLE_NAME(exception_name); \ VTABLE_TYPE(exception_name) { \ VTABLE_TYPE(parent_name) const * parent; \ size_t size; \ void (*copy)(exception_name * this, exception_name * other); \ void (*^?{})(exception_name & this); \ const char * (*msg)(exception_name * this); \ _CLOSE #define _VTABLE_INSTANCE(exception_name, parent_name, ...) \ VTABLE_TYPE(exception_name) const & get_exception_vtable(exception_name *) { \ return VTABLE_NAME(exception_name); \ } \ void _GLUE2(exception_name,_copy)(exception_name * this, exception_name * other) { \ *this = *other; \ } \ VTABLE_TYPE(exception_name) VTABLE_NAME(exception_name) @= { \ &VTABLE_NAME(parent_name), sizeof(exception_name), \ _GLUE2(exception_name,_copy), ^?{}, \ _CLOSE #define _FORALL_VTABLE_DECLARATION(exception_name, parent_name, assertions, \ parameters, parent_parameters) \ forall assertions struct exception_name; \ forall assertions VTABLE_TYPE(exception_name) { \ VTABLE_TYPE(parent_name) parent_parameters const * parent; \ size_t size; \ void (*copy)(exception_name parameters * this, exception_name parameters * other); \ void (*^?{})(exception_name parameters & this); \ const char * (*msg)(exception_name parameters * this); \ _CLOSE #define _POLY_VTABLE_INSTANCE(exception_name, parent_name, ...) \ extern VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name); \ VTABLE_TYPE(exception_name)(__VA_ARGS__) const & get_exception_vtable( \ exception_name(__VA_ARGS__) *) { \ return VTABLE_NAME(exception_name); \ } \ void _GLUE2(exception_name,_copy)( \ exception_name(__VA_ARGS__) * this, exception_name(__VA_ARGS__) * other) { \ *this = *other; \ } \ VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name) @= { \ &VTABLE_NAME(parent_name), sizeof(exception_name(__VA_ARGS__)), \ _GLUE2(exception_name,_copy), ^?{}, \ _CLOSE #define _IS_EXCEPTION(kind, exception_name, parameters, ...) \ kind(exception_name parameters, VTABLE_TYPE(exception_name) parameters)