Skip to content

Instantly share code, notes, and snippets.

@LiterallyVoid
Created January 26, 2022 06:19
Show Gist options
  • Select an option

  • Save LiterallyVoid/dc55dfd305e53560ef2134670577f8f2 to your computer and use it in GitHub Desktop.

Select an option

Save LiterallyVoid/dc55dfd305e53560ef2134670577f8f2 to your computer and use it in GitHub Desktop.
#define CONCAT2(x, y) x ## y
#define CONCAT(x, y) CONCAT2(x, y)
#define COMPONENT(...)
#define DEFEVENT(...)
#define DEFBUBBLE(...)
struct context {
#define DEFCONTEXT(type, name, default) type name;
#include "components.i"
#undef DEFCONTEXT
};
struct context context_default(void) {
struct context ctx;
#define DEFCONTEXT(type, name, default) ctx.name = default;
#include "components.i"
#undef DEFCONTEXT
return ctx;
}
#define DEFCONTEXT(...)
// EVENTS & BUBBLES
#undef DEFEVENT
#undef DEFBUBBLE
#define DEFEVENT(name, ...) struct event_##name { __VA_ARGS__ }; const int event_##name = __LINE__;
#define DEFBUBBLE(name, ...) struct bubble_##name { __VA_ARGS__ };
#include "components.i"
#undef DEFEVENT
#undef DEFBUBBLE
#define DEFEVENT(...)
#define DEFBUBBLE(...)
#undef DEFBUBBLE
#define DEFBUBBLE(name, ...) struct { void *data; void (*fn)(void *data, struct bubble_##name *event); } name;
struct bubble_handlers {
#include "components.i"
};
#undef DEFBUBBLE
#define DEFBUBBLE(...)
#undef COMPONENT
#define PROP(...)
#define STATE(...)
#define ON(...)
#define CATCH(...)
#define LET(...)
#define PROVIDE(...)
#define USE(...)
#define INSTANCE(...)
// DEFINE PROPS
#define COMPONENT(name, ...) struct name##_props { __VA_ARGS__ };
#undef PROP
#define PROP(type, name) type name;
#include "components.i"
#undef PROP
#define PROP(...)
#undef COMPONENT
// DEFINE STATES
#define COMPONENT(name, ...) struct name##_state { struct name##_props ens_props; struct context ctx; __VA_ARGS__ };
#undef STATE
#define STATE(type, name, ...) type name;
#undef INSTANCE
#define INSTANCE(component, ...) int CONCAT(ens_state_count_, __LINE__); int CONCAT(ens_state_count_pre_, __LINE__); struct component##_state CONCAT(ens_state_, __LINE__)[8];
#undef USE
#define USE(component, ...) int CONCAT(ens_state_count_, __LINE__); int CONCAT(ens_state_count_pre_, __LINE__); struct component##_state CONCAT(ens_state_, __LINE__)[8];
#include "components.i"
#undef STATE
#define STATE(...)
#undef USE
#define USE(...)
#undef INSTANCE
#define INSTANCE(...)
#undef COMPONENT
// DEFINE DEINITS
#define COMPONENT(name, ...) void name##_deinit(struct name##_state *state) { __VA_ARGS__ };
#undef INSTANCE
#define INSTANCE(component, ...) for (int i = 0; i < state->CONCAT(ens_state_count_, __LINE__); i++) component##_deinit(&state->CONCAT(ens_state_, __LINE__)[i]);
#undef USE
#define USE(component, ...) for (int i = 0; i < state->CONCAT(ens_state_count_, __LINE__); i++) component##_deinit(&state->CONCAT(ens_state_, __LINE__)[i]);
#include "components.i"
#undef USE
#define USE(...)
#undef INSTANCE
#define INSTANCE(...)
#undef COMPONENT
// DEFINE DEFAULT
#define COMPONENT(name, ...) void name##_default(struct name##_state *state) { __VA_ARGS__ };
#undef STATE
#define STATE(type, name, ...) state->name = __VA_ARGS__;
#undef INSTANCE
#define INSTANCE(component, ...) state->CONCAT(ens_state_count_, __LINE__) = 0;
#undef USE
#define USE(component, ...) state->CONCAT(ens_state_count_, __LINE__) = 0;
#include "components.i"
#undef STATE
#define STATE(...)
#undef USE
#define USE(...)
#undef INSTANCE
#define INSTANCE(...)
#undef COMPONENT
// DECLARE
#define COMPONENT(name, ...) \
struct context name##_build(struct name##_state *state, struct context ctx, struct name##_props props); \
struct context name##_init(struct name##_state *state, struct context ctx, struct name##_props props);
#include "components.i"
#undef COMPONENT
// DEFINE PREBUILDS
#define COMPONENT(name, ...) void name##_prebuild(struct name##_state *state) { __VA_ARGS__ };
#undef INSTANCE
#define INSTANCE(component, ...) state->CONCAT(ens_state_count_pre_, __LINE__) = state->CONCAT(ens_state_count_, __LINE__); state->CONCAT(ens_state_count_, __LINE__) = 0;
#undef USE
#define USE(component, ...) state->CONCAT(ens_state_count_pre_, __LINE__) = state->CONCAT(ens_state_count_, __LINE__); state->CONCAT(ens_state_count_, __LINE__) = 0;
#include "components.i"
#undef USE
#define USE(...)
#undef INSTANCE
#define INSTANCE(...)
#undef COMPONENT
// DEFINE POSTBUILDS
#define COMPONENT(name, ...) void name##_postbuild(struct name##_state *state) { __VA_ARGS__ };
#undef INSTANCE
#define INSTANCE(component, ...) for (int i = state->CONCAT(ens_state_count_, __LINE__); i < state->CONCAT(ens_state_count_pre_, __LINE__); i++) { component##_deinit(&state->CONCAT(ens_state_, __LINE__)[i]); }
#undef USE
#define USE(component, ...) for (int i = state->CONCAT(ens_state_count_, __LINE__); i < state->CONCAT(ens_state_count_pre_, __LINE__); i++) { component##_deinit(&state->CONCAT(ens_state_, __LINE__)[i]); }
#include "components.i"
#undef USE
#define USE(...)
#undef INSTANCE
#define INSTANCE(...)
#undef COMPONENT
// DEFINE BUILDS
#define COMPONENT(name, ...) struct context name##_build(struct name##_state *state, struct context ctx, struct name##_props props) { name##_prebuild(state); __VA_ARGS__ name##_postbuild(state); state->ctx = ctx; return ctx; };
#undef STATE
#define STATE(type, name, ...) type name = state->name;
#undef PROP
#define PROP(type, name) type name = props.name;
#undef PROVIDE
#define PROVIDE(name, ...) ctx.name = __VA_ARGS__;
#undef LET
#define LET(type_value, ...) type_value = __VA_ARGS__;
#define CTX(name) ctx.name
#undef INSTANCE
#define INSTANCE(component, ...) if (state->CONCAT(ens_state_count_, __LINE__) < state->CONCAT(ens_state_count_, __LINE__)) { \
component##_build(&state->CONCAT(ens_state_, __LINE__)[state->CONCAT(ens_state_count_, __LINE__)++], ctx, (struct component##_props) { __VA_ARGS__ }); \
} else { \
component##_init(&state->CONCAT(ens_state_, __LINE__)[state->CONCAT(ens_state_count_, __LINE__)++], ctx, (struct component##_props) { __VA_ARGS__ }); \
} \
#undef USE
#define USE(component, ...) if (state->CONCAT(ens_state_count_, __LINE__) < state->CONCAT(ens_state_count_, __LINE__)) { \
ctx = component##_build(&state->CONCAT(ens_state_, __LINE__)[state->CONCAT(ens_state_count_, __LINE__)++], ctx, (struct component##_props) { __VA_ARGS__ }); \
} else { \
ctx = component##_init(&state->CONCAT(ens_state_, __LINE__)[state->CONCAT(ens_state_count_, __LINE__)++], ctx, (struct component##_props) { __VA_ARGS__ }); \
} \
#include "components.i"
#undef STATE
#define STATE(...)
#undef PROP
#define PROP(...)
#undef PROVIDE
#define PROVIDE(...)
#undef LET
#define LET(...)
#undef CTX
#define CTX(...)
#undef USE
#define USE(...)
#undef INSTANCE
#define INSTANCE(...)
#undef COMPONENT
// DEFINE INITS
#define COMPONENT(name, ...) struct context name##_init(struct name##_state *state, struct context ctx, struct name##_props props) { name##_default(state); name##_build(state, ctx, props); };
#include "components.i"
#undef COMPONENT
// EVENT HANDLERS
#define BUBBLE(x, ...) bubble_handlers.x.fn(bubble_handlers.x.data, &(struct bubble_##x) { __VA_ARGS__ });
#define COMPONENT(name, ...) __VA_ARGS__
#undef CATCH
#define CATCH(event, e, ...) void CONCAT(ens_bubble_handler_, __LINE__)(void *data, struct bubble_##event *e) { __VA_ARGS__ }
#include "components.i"
#undef CATCH
#define CATCH(...)
#undef COMPONENT
#undef CTX
#define CTX(name) state->ctx.name
#define COMPONENT(name, ...) void name##_event_i(struct name##_state *state, int event, void *event_data, struct bubble_handlers bubble_handlers) { __VA_ARGS__ } void name##_event(struct name##_state *state, int event, void *event_data) { name##_event_i(state, event, event_data, (struct bubble_handlers) { 0 }); name##_build(state, context_default(), state->ens_props); }
#undef STATE
#define STATE(type, name, ...) type *name = &state->name;
#undef ON
#define ON(ev, e, ...) if (event == event_##ev) { struct event_##ev *e = event_data; __VA_ARGS__ }
#undef CATCH
#define CATCH(ev, e, ...) bubble_handlers.ev.data = state; bubble_handlers.ev.fn = CONCAT(ens_bubble_handler_, __LINE__);
#undef USE
#define USE(component, ...) for (int i = 0; i < state->CONCAT(ens_state_count_, __LINE__); i++) { component##_event_i(&state->CONCAT(ens_state_, __LINE__)[i], event, event_data, bubble_handlers); }
#undef INSTANCE
#define INSTANCE(component, ...) for (int i = 0; i < state->CONCAT(ens_state_count_, __LINE__); i++) { component##_event_i(&state->CONCAT(ens_state_, __LINE__)[i], event, event_data, bubble_handlers); }
#include "components.i"
#undef ON
#define ON(...)
#undef COMPONENT
#undef DEFCONTEXT
#undef DEFEVENT
#undef DEFBUBBLE
#undef PROP
#undef STATE
#undef ON
#undef CATCH
#undef LET
#undef PROVIDE
#undef USE
#undef INSTANCE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment