Files
object-lisp/include/lisp/method_macro.h
2025-09-03 03:20:58 -07:00

140 lines
5.8 KiB
C

#ifndef INCLUDED_METHOD_MACRO_H
#define INCLUDED_METHOD_MACRO_H
#if __has_attribute(always_inline)
# define always_inline inline __attribute__((always_inline))
#else
# define always_inline inline
#endif
#if __has_attribute(unused)
# define UNUSED __attribute__((unused))
#else
# define UNUSED
#endif
// clang-format off
#define _ELEVENTH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, ...) a11
#define _COUNT_ARGS(...) _ELEVENTH(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define _GLUE(a, b) a##b
#define _GLUE2(a, b) _GLUE(a, b)
#define _IGNORE(...)
#define _REMOVE_FIRST(a1, ...) __VA_ARGS__
#define _EVAL(...) __VA_ARGS__
// clang-format on
// This is needed because C11 doesn't allow empty __VA_ARGS__
#define _GET_1_1(a1) a1
#define _GET_1_2(a1, a2) a1
#define _GET_1_3(a1, a2, a3) a1
#define _GET_1_4(a1, a2, a3, a4) a1
#define _GET_1_5(a1, a2, a3, a4, a5) a1
#define _GET_1_6(a1, a2, a3, a4, a5, a6) a1
#define _GET_2_2(a1, a2) a2
#define _GET_2_3(a1, a2, a3) a2
#define _GET_2_4(a1, a2, a3, a4) a2
#define _GET_2_5(a1, a2, a3, a4, a5) a2
#define _GET_2_6(a1, a2, a3, a4, a5, a6) a2
#define _GET_3_3(a1, a2, a3) a3
#define _GET_3_4(a1, a2, a3, a4) a3
#define _GET_3_5(a1, a2, a3, a4, a5) a3
#define _GET_3_6(a1, a2, a3, a4, a5, a6) a3
#define _GET_4_4(a1, a2, a3, a4) a4
#define _GET_4_5(a1, a2, a3, a4, a5) a4
#define _GET_4_6(a1, a2, a3, a4, a5, a6) a4
#define _GET_5_5(a1, a2, a3, a4, a5) a5
#define _GET_5_6(a1, a2, a3, a4, a5, a6) a5
#define _GET_6_6(a1, a2, a3, a4, a5, a6) a6
#define _GET_NTH(n, args) \
_EVAL(_GLUE2(_GLUE2(_GLUE2(_GET_, n), _), _COUNT_ARGS args) args)
#define METHOD_CALLBACK_NAME(name) _##name##__as_callback
#define _CB_DECL_ARGS_1 Object *
#define _CB_DECL_ARGS_2 Object *, _CB_DECL_ARGS_1
#define _CB_DECL_ARGS_3 Object *, _CB_DECL_ARGS_2
#define _CB_DECL_ARGS_4 Object *, _CB_DECL_ARGS_3
#define _CB_DECL_ARGS_5 Object *, _CB_DECL_ARGS_4
#define _CB_DECL_ARGS_6 Object *, _CB_DECL_ARGS_5
#define _CB_DECL_ARGS_N(count) (_GLUE(_CB_DECL_ARGS_, count))
#define _CB_DECL_ARGS_FOR(...) _CB_DECL_ARGS_N(_COUNT_ARGS(__VA_ARGS__))
#define _GEN_CB_DECL(name, args) \
Object *METHOD_CALLBACK_NAME(name) \
_CB_DECL_ARGS_FOR args
#define _ARG_NAME_1(args) _IGNORE _GET_NTH(1, args)
#define _ARG_NAME_2(args) _IGNORE _GET_NTH(2, args)
#define _ARG_NAME_3(args) _IGNORE _GET_NTH(3, args)
#define _ARG_NAME_4(args) _IGNORE _GET_NTH(4, args)
#define _ARG_NAME_5(args) _IGNORE _GET_NTH(5, args)
#define _ARG_NAME_6(args) _IGNORE _GET_NTH(6, args)
#define _ARG_NAME_N(n, args) _EVAL(_GLUE(_ARG_NAME_, n)(args))
#define _VOID_ARG_N(n, args) (void *) _ARG_NAME_N(n, args)
#define _CALL_ARGS_1(args) _VOID_ARG_N(1, args)
#define _CALL_ARGS_2(args) _CALL_ARGS_1(args), _VOID_ARG_N(2, args)
#define _CALL_ARGS_3(args) _CALL_ARGS_2(args), _VOID_ARG_N(3, args)
#define _CALL_ARGS_4(args) _CALL_ARGS_3(args), _VOID_ARG_N(4, args)
#define _CALL_ARGS_5(args) _CALL_ARGS_4(args), _VOID_ARG_N(5, args)
#define _CALL_ARGS_6(args) _CALL_ARGS_5(args), _VOID_ARG_N(6, args)
#define _CALL_ARGS_N(n, args) _GLUE(_CALL_ARGS_, n)(args)
#define _GEN_REAL_CALL(name, args) \
METHOD_CALLBACK_NAME(name)(_CALL_ARGS_N(_COUNT_ARGS args, args))
#define _UNWRAP_TYPE(arg) _EVAL arg
#define _UNWRAP_ARG_N(n, args) _UNWRAP_TYPE(_GET_NTH(n, args))
#define _UNWRAP_ARGS_1(args) _UNWRAP_ARG_N(1, args)
#define _UNWRAP_ARGS_2(args) _UNWRAP_ARGS_1(args), _UNWRAP_ARG_N(2, args)
#define _UNWRAP_ARGS_3(args) _UNWRAP_ARGS_2(args), _UNWRAP_ARG_N(3, args)
#define _UNWRAP_ARGS_4(args) _UNWRAP_ARGS_3(args), _UNWRAP_ARG_N(4, args)
#define _UNWRAP_ARGS_5(args) _UNWRAP_ARGS_4(args), _UNWRAP_ARG_N(5, args)
#define _UNWRAP_ARGS_6(args) _UNWRAP_ARGS_5(args), _UNWRAP_ARG_N(6, args)
#define _UNWRAP_ARGS_N(n, args) _GLUE(_UNWRAP_ARGS_, n)(args)
#define _UNWRAP_ARGS(args) _UNWRAP_ARGS_N(_COUNT_ARGS args, args)
#define _METHOD_RAW(rtype, ret_stmt, name, args) \
_GEN_CB_DECL(name, args); \
static always_inline rtype name(_UNWRAP_ARGS(args)) { \
ret_stmt _GEN_REAL_CALL(name, args); \
} \
struct __dummy_struct
#define METHOD(rtype, name, args) _METHOD_RAW(rtype, return (rtype), name, args)
#define VOID_METHOD(name, args) _METHOD_RAW(void, , name, args)
#define _CB_DEF_ARGS_1 Object *_internal_arg1
#define _CB_DEF_ARGS_2 _CB_DEF_ARGS_1, Object *_internal_arg2
#define _CB_DEF_ARGS_3 _CB_DEF_ARGS_2, Object *_internal_arg3
#define _CB_DEF_ARGS_4 _CB_DEF_ARGS_3, Object *_internal_arg4
#define _CB_DEF_ARGS_5 _CB_DEF_ARGS_4, Object *_internal_arg5
#define _CB_DEF_ARGS_6 _CB_DEF_ARGS_5, Object *_internal_arg6
#define _CB_DEF_ARGS_N(count) (_GLUE(_CB_DEF_ARGS_, count))
#define _CB_DEF_ARGS_FOR(...) _CB_DEF_ARGS_N(_COUNT_ARGS(__VA_ARGS__))
#define _GEN_CB_DEF(name, args) \
Object *METHOD_CALLBACK_NAME(name) \
_CB_DEF_ARGS_FOR args
#define _SET_NTH_ARG(n, args) \
UNUSED _GET_NTH(n, args) = (void *) _internal_arg##n;
#define _SET_ARGS_1(args) _SET_NTH_ARG(1, args)
#define _SET_ARGS_2(args) _SET_ARGS_1(args) _SET_NTH_ARG(2, args)
#define _SET_ARGS_3(args) _SET_ARGS_2(args) _SET_NTH_ARG(3, args)
#define _SET_ARGS_4(args) _SET_ARGS_3(args) _SET_NTH_ARG(4, args)
#define _SET_ARGS_5(args) _SET_ARGS_4(args) _SET_NTH_ARG(5, args)
#define _SET_ARGS_6(args) _SET_ARGS_5(args) _SET_NTH_ARG(6, args)
#define _SET_ARGS_N(n, args) _GLUE(_SET_ARGS_, n)(args)
#define DEFINE_METHOD(rtype, name, args, body) \
_GEN_CB_DEF(name, args) { \
_SET_ARGS_N(_COUNT_ARGS args, args) \
body \
}
#endif