summaryrefslogtreecommitdiff
path: root/libmisc
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-02-10 00:06:34 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-02-10 00:06:34 -0700
commit6cd125e1ffd44fdf62c44d22c519561a8c9d7268 (patch)
treebf2b4a8225fe0d6f00084a1577c70bb564a20600 /libmisc
parentf466cff948ec638f26a9a77a391904ebe03c4dfb (diff)
parenta51875001eb672d73c9d84d44bb32abce327b931 (diff)
Merge branch 'lukeshu/libobj-simple'
Diffstat (limited to 'libmisc')
-rw-r--r--libmisc/CMakeLists.txt5
-rw-r--r--libmisc/include/libmisc/macro.h41
-rw-r--r--libmisc/include/libmisc/vcall.h28
-rw-r--r--libmisc/tests/test_vcall.c74
4 files changed, 42 insertions, 106 deletions
diff --git a/libmisc/CMakeLists.txt b/libmisc/CMakeLists.txt
index 8d842c3..f8f15bc 100644
--- a/libmisc/CMakeLists.txt
+++ b/libmisc/CMakeLists.txt
@@ -1,6 +1,6 @@
-# libmisc/CMakeLists.txt - A simple Go-ish object system built on GCC -fplan9-extensions
+# libmisc/CMakeLists.txt - TODO
#
-# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
# SPDX-License-Identifier: AGPL-3.0-or-later
add_library(libmisc INTERFACE)
@@ -20,4 +20,3 @@ add_lib_test(libmisc test_log)
add_lib_test(libmisc test_macro)
add_lib_test(libmisc test_private)
add_lib_test(libmisc test_rand)
-add_lib_test(libmisc test_vcall)
diff --git a/libmisc/include/libmisc/macro.h b/libmisc/include/libmisc/macro.h
index 9bb068f..d11b99f 100644
--- a/libmisc/include/libmisc/macro.h
+++ b/libmisc/include/libmisc/macro.h
@@ -1,6 +1,6 @@
/* libmisc/macro.h - Useful C preprocessor macros
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -36,6 +36,7 @@
/* macro arguments */
+#define LM_FIRST(a, ...) a
#define LM_SECOND(a, b, ...) b
#define LM_EAT(...)
#define LM_EXPAND(...) __VA_ARGS__
@@ -52,4 +53,42 @@
#define _LM_IF__xxTxx(...) __VA_ARGS__ LM_EAT
#define _LM_IF__xxFxx(...) LM_EXPAND
+/* tuples */
+
+#define LM_IS_TUPLE(x) LM_IS_SENTINEL(_LM_IS_TUPLE x)
+#define _LM_IS_TUPLE(...) LM_SENTINEL()
+
+/* `tuples` is a sequence of `(tuple1)(tuple2)(tuple3)` */
+#define _LM_TUPLES_COMMA(tuple...) (tuple),
+#define LM_TUPLES_NONEMPTY(tuples) LM_IS_TUPLE(_LM_TUPLES_COMMA tuples)
+#define LM_TUPLES_HEAD(tuples) LM_EXPAND(LM_FIRST LM_EAT() (_LM_TUPLES_COMMA tuples))
+#define LM_TUPLES_TAIL(tuples) LM_EAT tuples
+
+/* iteration */
+
+/* BUG: LM_FOREACH_TUPLE maxes out at 1024 tuples. */
+#define LM_FOREACH_TUPLE(tuples, func, ...) \
+ _LM_EVAL(_LM_FOREACH_TUPLE(tuples, func, __VA_ARGS__))
+#define _LM_FOREACH_TUPLE(tuples, func, ...) \
+ LM_IF(LM_TUPLES_NONEMPTY(tuples))( \
+ _LM_DEFER2(func)(__VA_ARGS__ __VA_OPT__(,) LM_EXPAND LM_TUPLES_HEAD(tuples)) \
+ _LM_DEFER2(_LM_FOREACH_TUPLE_indirect)()(LM_TUPLES_TAIL(tuples), func, __VA_ARGS__) \
+ )()
+#define _LM_FOREACH_TUPLE_indirect() _LM_FOREACH_TUPLE
+
+#define _LM_DEFER2(macro) macro LM_EAT LM_EAT()()
+
+#define _LM_EVAL(...) _LM_EVAL__1024(__VA_ARGS__) /* 1024 iterations aught to be enough for anybody */
+#define _LM_EVAL__1024(...) _LM_EVAL__512(_LM_EVAL__512(__VA_ARGS__))
+#define _LM_EVAL__512(...) _LM_EVAL__256(_LM_EVAL__256(__VA_ARGS__))
+#define _LM_EVAL__256(...) _LM_EVAL__128(_LM_EVAL__128(__VA_ARGS__))
+#define _LM_EVAL__128(...) _LM_EVAL__64(_LM_EVAL__64(__VA_ARGS__))
+#define _LM_EVAL__64(...) _LM_EVAL__32(_LM_EVAL__32(__VA_ARGS__))
+#define _LM_EVAL__32(...) _LM_EVAL__16(_LM_EVAL__16(__VA_ARGS__))
+#define _LM_EVAL__16(...) _LM_EVAL__8(_LM_EVAL__8(__VA_ARGS__))
+#define _LM_EVAL__8(...) _LM_EVAL__4(_LM_EVAL__4(__VA_ARGS__))
+#define _LM_EVAL__4(...) _LM_EVAL__2(_LM_EVAL__2(__VA_ARGS__))
+#define _LM_EVAL__2(...) _LM_EVAL__1(_LM_EVAL__1(__VA_ARGS__))
+#define _LM_EVAL__1(...) __VA_ARGS__
+
#endif /* _LIBMISC_MACRO_H_ */
diff --git a/libmisc/include/libmisc/vcall.h b/libmisc/include/libmisc/vcall.h
deleted file mode 100644
index 31a8c7e..0000000
--- a/libmisc/include/libmisc/vcall.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* libmisc/vcall.h - A simple Go-ish object system built on GCC -fplan9-extensions
- *
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-#ifndef _LIBMISC_VCALL_H_
-#define _LIBMISC_VCALL_H_
-
-#include <stddef.h> /* for offsetof() */
-
-#include <libmisc/assert.h>
-
-#define VCALL(o, m, ...) \
- ({ \
- assert(o); \
- (o)->vtable->m(o __VA_OPT__(,) __VA_ARGS__); \
- })
-
-#define VCALL_SELF(obj_typ, iface_typ, iface_ptr) \
- ({ \
- static_assert(_Generic(iface_ptr, iface_typ *: 1, default: 0), \
- "typeof("#iface_ptr") != "#iface_typ" *"); \
- assert(iface_ptr); \
- ((obj_typ*)(((void*)iface_ptr)-offsetof(obj_typ,iface_typ))); \
- })
-
-#endif /* _LIBMISC_VCALL_H_ */
diff --git a/libmisc/tests/test_vcall.c b/libmisc/tests/test_vcall.c
deleted file mode 100644
index f36fc4b..0000000
--- a/libmisc/tests/test_vcall.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* libmisc/tests/test_vcall.c - Tests for <libmisc/vcall.h>
- *
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-#include <libmisc/assert.h>
-#include <libmisc/vcall.h>
-
-#include "test.h"
-
-/******************************************************************************/
-
-struct frobber_vtable;
-
-typedef struct {
- struct frobber_vtable *vtable;
-} implements_frobber;
-
-struct frobber_vtable {
- int (*frob)(implements_frobber *);
- int (*frob1)(implements_frobber *, int);
- void (*frob0)(implements_frobber *);
-};
-
-/******************************************************************************/
-
-struct myclass {
- int a;
- implements_frobber;
-};
-static_assert(offsetof(struct myclass, implements_frobber) != 0);
-
-static int myclass_frob(implements_frobber *_self) {
- struct myclass *self = VCALL_SELF(struct myclass, implements_frobber, _self);
- test_assert(self);
- test_assert((void*)self != (void*)_self);
- return self->a;
-}
-
-static int myclass_frob1(implements_frobber *_self, int arg) {
- struct myclass *self = VCALL_SELF(struct myclass, implements_frobber, _self);
- test_assert(self);
- test_assert((void*)self != (void*)_self);
- return arg;
-}
-
-static void myclass_frob0(implements_frobber *_self) {
- struct myclass *self = VCALL_SELF(struct myclass, implements_frobber, _self);
- test_assert(self);
- test_assert((void*)self != (void*)_self);
-}
-
-struct frobber_vtable myclass_vtable = {
- .frob = myclass_frob,
- .frob1 = myclass_frob1,
- .frob0 = myclass_frob0,
-};
-
-/******************************************************************************/
-
-#define MAGIC1 909837
-#define MAGIC2 657441
-
-int main() {
- struct myclass obj = {
- .implements_frobber = { .vtable = &myclass_vtable },
- .a = MAGIC1,
- };
- test_assert(VCALL(&obj, frob) == MAGIC1);
- test_assert(VCALL(&obj, frob1, MAGIC2) == MAGIC2);
- VCALL(&obj, frob0);
- return 0;
-}