diff options
author | Michael Smith <mikesmiffy128@gmail.com> | 2022-09-13 21:46:21 +0100 |
---|---|---|
committer | Michael Smith <mikesmiffy128@gmail.com> | 2022-09-13 22:50:30 +0100 |
commit | 792463cb133f65645feb48743bbc03ef8eb96bdd (patch) | |
tree | 3879cd6895fe5c8f597f445af2410a41bcf00f73 /src/event.h | |
parent | 378892d089b6742a95b8d573af58535597f19d25 (diff) |
Move towards C23, improve events and vcall macros
Another big one. Here's a list of things:
- Since the upcoming C23 standardises typeof(), use it as an extension
for the time being in order to allow passing arbitrary types as
macro/codegen parameters. It wouldn't have been a big leap to do this
even without standardisation since it's apparently an easy extension
to implement - and also, to be honest, this project is essentially glued
to Clang anyway so who cares.
- Likewise, bool, true and false are becoming pre-defined, so
pre-pre-define them now in order to get the benefit of not having to
remember one header everywhere.
- Really ungodly/amazing vcall macro stuff now allows us to call C++
virtual functions like regular C functions. It's pretty cool!
- Events can now take arbitrary parameters and come in two types:
regular events and predicates.
All this makes the base code even uglier but makes the feature
implementation nicer. In other words, it places more of the cognitive
burden on myself and less on other people who might want to contribute.
This is a good tradeoff, because I'm a genius.
Diffstat (limited to 'src/event.h')
-rw-r--r-- | src/event.h | 56 |
1 files changed, 47 insertions, 9 deletions
diff --git a/src/event.h b/src/event.h index e439201..86a443e 100644 --- a/src/event.h +++ b/src/event.h @@ -20,15 +20,53 @@ #define _EVENT_CAT4_(a, b, c, d) a##b##c##d #define _EVENT_CAT4(a, b, c, d) _EVENT_CAT4_(a, b, c, d) -#define DECL_EVENT(evname) void _evemit_##evname(void); -#define DEF_EVENT(evname) \ - DECL_EVENT(evname) \ - static inline void _evown_##evname(void) { _evemit_##evname(); } -#define EMIT_EVENT(evname) _evown_##evname() - -#define HANDLE_EVENT(evname) \ - void _EVENT_CAT4(_evhandler_, MODULE_NAME, _, evname)(void) \ - /* function body here */ +/* + * Declares an event defined somewhere in the codebase, allowing a handler to be + * defined with HANDLE_EVENT() below. Takes an optional list of types for + * parameters. The handler will be called every time the event is emitted by the + * declaring module. + */ +#define DECL_EVENT(evname, ...) typedef void _must_declare_event_##evname; + +/* + * Declares a predicate - a special type of even returning bool. Predicates are + * used to determine whether some other action should be performed, and + * generally should not have side effects, since they get short-circuited and + * thus won't always fire when a check is being performed. + */ +#define DECL_PREDICATE(evname, ...) typedef bool _must_declare_event_##evname; + +/* + * Defines an event belonging to this module. Doing so allows EMIT_<event>() to + * be called to fire handlers in all modules. Two modules (i.e. source files) + * cannot define an event (or predicate) with the same name. + */ +#define DEF_EVENT(event, ...) void EMIT_##event(__VA_ARGS__); + +/* + * Defines a predicate belonging to this module. Doing so allows CHECK_<pred>() + * to be called to determine whether to perform some action. Predicates share a + * namespace with events and two modules cannot define two things with the same + * name. + */ +#define DEF_PREDICATE(pred, ...) bool CHECK_##pred(__VA_ARGS__); + +/* + * Begins an event handler function that gets hooked up to an event by the code + * generation system. This is type-generic: if the event is a regular event, + * the function will return void; if it is a predicate it will return bool. + * Takes a function argument list which must match the type lists given to the + * above DEF/DECL macros. + * + * Note again that predicates are not guaranteed to fire at all due to + * short-circuiting and thus generally should not have side effects. + * + * In the current event implementation, each source file may handle only one of + * each event type, as any more wouldn't be too useful anyway. + */ +#define HANDLE_EVENT(evname, ...) \ + _must_declare_event_##evname _EVENT_CAT4(_evhandler_, MODULE_NAME, _, \ + evname)(__VA_ARGS__) /* function body here */ #endif |