From d19a8749f4faa85eaa324e48e1b49ba6019574f4 Mon Sep 17 00:00:00 2001 From: Axy Date: Mon, 18 May 2026 15:37:52 +0200 Subject: [PATCH] Stub builtin impl and fixed weirdness with clang --- .deps | 3 ++ Makefile | 2 +- conf.mk | 6 ++-- src/arc.h | 2 +- src/atomic.h | 4 +-- src/builtin_noop.c | 29 ++++++++++++++++ src/ccera.h | 5 +-- src/eval.c | 83 ++++++++++++++++++++++++++++++-------------- src/panic.c | 14 ++++++-- src/value.h | 4 ++- src/value_get.h | 10 +++++- src/value_lifetime.c | 14 +++++--- src/value_list.c | 13 ++++--- src/value_move.c | 8 ++++- src/value_new.c | 19 ++++++++-- src/value_new.h | 4 ++- src/value_types.h | 17 +++++++-- test.c | 4 ++- 18 files changed, 183 insertions(+), 58 deletions(-) create mode 100644 src/builtin_noop.c diff --git a/.deps b/.deps index 3fe262b..9126ff5 100644 --- a/.deps +++ b/.deps @@ -1,5 +1,8 @@ ${BUILDDIR}/arc.o: src/arc.c src/arc.h src/memutils.h src/panic.h src/jmp.h \ src/arith.h src/atomic.h +${BUILDDIR}/builtin_noop.o: src/builtin_noop.c src/memutils.h src/panic.h src/jmp.h \ + src/value.h src/value_get.h src/value_types.h src/value_new.h \ + src/arc.h src/arith.h ${BUILDDIR}/defer.o: src/defer.c src/defer.h src/framealloc.h src/align.h \ src/stacktrack.h src/memutils.h src/panic.h src/jmp.h ${BUILDDIR}/eval.o: src/eval.c src/ccera.h src/jmp.h src/defer.h src/framealloc.h \ diff --git a/Makefile b/Makefile index 394da50..332ebf2 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ NAME=ccera.a -SRCS=src/arc.c src/defer.c src/eval.c src/framealloc.c src/panic.c src/stacktrack.c src/value_lifetime.c src/value_list.c src/value_move.c src/value_new.c +SRCS=src/arc.c src/builtin_noop.c src/defer.c src/eval.c src/framealloc.c src/panic.c src/stacktrack.c src/value_lifetime.c src/value_list.c src/value_move.c src/value_new.c HEADERS=src/align.h src/arc.h src/arith.h src/atomic.h src/ccera.h src/defer.h src/framealloc.h src/jmp.h src/memutils.h src/panic.h src/stacktrack.h src/value_get.h src/value.h src/value_new.h src/value_types.h diff --git a/conf.mk b/conf.mk index 6c11b81..3ee296e 100644 --- a/conf.mk +++ b/conf.mk @@ -1,5 +1,5 @@ -#LTO=1 -CC=gcc +LTO=1 +#CC=gcc #UBSAN=1 -TSAN=1 +#TSAN=1 #ASAN=1 diff --git a/src/arc.h b/src/arc.h index 5c5f72e..1af6e76 100644 --- a/src/arc.h +++ b/src/arc.h @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/13 08:56:53 by agilliar #+# #+# */ -/* Updated: 2026/05/14 15:55:35 by agilliar ### ########.fr */ +/* Updated: 2026/05/18 14:43:36 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/atomic.h b/src/atomic.h index c926672..53e9d1d 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/15 11:18:31 by agilliar #+# #+# */ -/* Updated: 2026/05/15 11:23:58 by agilliar ### ########.fr */ +/* Updated: 2026/05/18 13:11:57 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,7 +15,7 @@ # include -# if __has_feature(thread_sanitizer) +# ifdef __SANITIZE_THREAD__ __attribute__((always_inline)) static inline void acquire_fence_on(size_t *p) diff --git a/src/builtin_noop.c b/src/builtin_noop.c new file mode 100644 index 0000000..71cb146 --- /dev/null +++ b/src/builtin_noop.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* builtin_noop.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/05/18 14:35:11 by agilliar #+# #+# */ +/* Updated: 2026/05/18 15:01:29 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "memutils.h" +#include "value.h" +#include "arc.h" + +#include + +static t_value builtin_noop_impl(t_value self, t_value val) +{ + value_drop(&self); + printf("In noop!\n"); + return (val); +} + +t_value builtin_noop(void) +{ + return (value_new_builtin(&builtin_noop_impl, &noop, 0)); +} diff --git a/src/ccera.h b/src/ccera.h index e9a3dea..cc1d745 100644 --- a/src/ccera.h +++ b/src/ccera.h @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/04/29 16:08:57 by agilliar #+# #+# */ -/* Updated: 2026/05/15 11:21:51 by agilliar ### ########.fr */ +/* Updated: 2026/05/18 14:47:29 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -41,6 +41,7 @@ // move is whether said value shall be moved out // // This function takes ownership -t_value expr_eval(t_value expr); +t_value expr_eval(t_value eval, t_value arg); +t_value builtin_noop(void); #endif diff --git a/src/eval.c b/src/eval.c index c73cf45..0db5e30 100644 --- a/src/eval.c +++ b/src/eval.c @@ -6,23 +6,57 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/04 01:21:34 by agilliar #+# #+# */ -/* Updated: 2026/05/14 14:58:19 by agilliar ### ########.fr */ +/* Updated: 2026/05/18 15:00:10 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ #include "ccera.h" -// Has ownership of the values given -t_value eval_step(t_value arg, t_value *exprs, uintptr_t *i) +void step_extract(t_value *exprs, uintptr_t *i, t_value *eval, t_value *arg) { - (void) arg; - (void) exprs; - (void) i; - return (value_new_nil()); + uintptr_t pos; + uintptr_t mov; + + pos = *value_uint(value_list_get(*value_list_get(*exprs, *i), 0)); + mov = *value_uint(value_list_get(*value_list_get(*exprs, *i), 1)); + if (mov) + value_swap(value_list_getu(exprs, pos), eval); + else + value_put(eval, value_copy(*value_list_getu(exprs, pos))); + pos = *value_uint(value_list_get(*value_list_get(*exprs, *i), 2)); + mov = *value_uint(value_list_get(*value_list_get(*exprs, *i), 3)); + if (mov) + value_swap(value_list_getu(exprs, pos), arg); + else + value_put(arg, value_copy(*value_list_getu(exprs, pos))); +} + +void compound_eval(t_value *eval, t_value *arg) +{ + t_value *exprs; + uintptr_t *i; + t_value step_eval; + t_value step_arg; + + step_eval = value_new_nil(); + defer(value_drop, &step_eval); + step_arg = value_new_nil(); + defer(value_drop, &step_arg); + exprs = value_list_getu(eval, 0); + i = value_uint(value_list_getu(eval, 1)); + value_swap(value_list_getu(exprs, (*i)++), arg); + step_extract(exprs, i, &step_eval, &step_arg); + if (value_list_len(*exprs) + 1 == *i) + return (value_swap(eval, &step_eval), value_swap(arg, &step_arg)); + value_put(arg, expr_eval( + value_take_nil(&step_eval), value_take_nil(&step_arg))); +} + +void builtin_eval(t_value eval, t_value *arg) +{ + value_put(arg, value_builtin(&eval)->f(eval, value_take_nil(arg))); } -// The expression value is a tuple of an evaluatable and the argument to give it -// // Value-evaluatables are laid out as follows: // ( // ((values | nil)* .. (exprs | nil)*), @@ -33,30 +67,25 @@ t_value eval_step(t_value arg, t_value *exprs, uintptr_t *i) // The nil expressions are locations where an argument is expected, halting // evaluation // An expression is as follows: -// (eval_idx, arg_idx, move) +// (eval_idx, eval_move, arg_idx, arg_move) // eval_idx is the index of the function to be evaluated // arg_idx is the index of the argument to said function // move is whether said value shall be moved out // // This function takes ownership -t_value expr_eval(t_value expr) +t_value expr_eval(t_value eval, t_value arg) { - t_value *eval; - t_value arg; - t_value *exprs; - uintptr_t *i; - - defer(value_drop, &expr); - eval = value_list_getu(&expr, 0); - arg = value_take_nil(value_list_getu(&expr, 1)); - exprs = value_list_getu(eval, 0); - i = value_uint(value_list_getu(eval, 1)); - (void) exprs; - (void) i; - while (*i < value_list(exprs)->len) + defer(value_drop, &eval); + errdefer(value_drop, &arg); + while (true) { - eval_step(arg, exprs, i); - (*i)++; + if (eval.tag == VALUE_BUILTIN) + { + return (builtin_eval(value_take_nil(&eval), &arg), arg); + } + else if (eval.tag == VALUE_LIST) + compound_eval(&eval, &arg); + else + panic("Invalid type for evaluatable"); } - return (value_take_nil(value_list_getu(eval, (*i) - 1))); } diff --git a/src/panic.c b/src/panic.c index b06f9da..90496f5 100644 --- a/src/panic.c +++ b/src/panic.c @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/05 15:38:33 by agilliar #+# #+# */ -/* Updated: 2026/05/15 11:04:14 by agilliar ### ########.fr */ +/* Updated: 2026/05/18 15:36:28 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,6 +20,14 @@ t_panic_info *panic_store(void) return (&store); } +// Scuffed but clang is adament on not doing proper analysis on the semantics +// of setjmp/longjmp +__attribute__((noinline)) +static t_panic_info *panic_store2(void) +{ + return (panic_store()); +} + void *catch(void *f, void *dat) { void *res; @@ -29,8 +37,8 @@ void *catch(void *f, void *dat) panic_store()->stacktrack_pos = stacktrack_pos(); if (__builtin_setjmp((void *)&panic_store()->jmp)) { - res = panic_store()->data; - *panic_store() = prev; + res = panic_store2()->data; + *panic_store2() = prev; return (res); } ((void (*)(void *))f)(dat); diff --git a/src/value.h b/src/value.h index 9c2cc85..971422b 100644 --- a/src/value.h +++ b/src/value.h @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/12 16:14:16 by agilliar #+# #+# */ -/* Updated: 2026/05/13 22:20:49 by agilliar ### ########.fr */ +/* Updated: 2026/05/18 12:48:22 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,11 +25,13 @@ t_value value_clone(t_value val); void value_drop(t_value *value); t_value value_unique(t_value *val); +size_t value_list_len(t_value lst); t_value *value_list_get(t_value lst, size_t i); t_value *value_list_getu(t_value *lst, size_t i); void value_swap(t_value *a, t_value *b); t_value value_take(t_value *a, t_value b); t_value value_take_nil(t_value *a); +void value_put(t_value *a, t_value b); #endif diff --git a/src/value_get.h b/src/value_get.h index a33c66f..445fcea 100644 --- a/src/value_get.h +++ b/src/value_get.h @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/13 22:01:24 by agilliar #+# #+# */ -/* Updated: 2026/05/13 22:29:29 by agilliar ### ########.fr */ +/* Updated: 2026/05/18 14:49:16 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -48,4 +48,12 @@ static inline t_bytes *value_bytes(t_value *value) return (value->val.v_bytes); } +__attribute__((always_inline)) +static inline t_builtin *value_builtin(t_value *value) +{ + if (value->tag != VALUE_BUILTIN) + panic("Expected value to be builtin"); + return (value->val.v_builtin); +} + #endif diff --git a/src/value_lifetime.c b/src/value_lifetime.c index d37290f..fe8396e 100644 --- a/src/value_lifetime.c +++ b/src/value_lifetime.c @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/12 17:42:10 by agilliar #+# #+# */ -/* Updated: 2026/05/13 22:29:20 by agilliar ### ########.fr */ +/* Updated: 2026/05/18 14:34:35 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,6 +22,8 @@ t_value value_copy(t_value val) arc_copy(val.val.v_bytes); else if (val.tag == VALUE_LIST) arc_copy(val.val.v_list); + else if (val.tag == VALUE_BUILTIN) + arc_copy(val.val.v_builtin); return (val); } @@ -50,7 +52,7 @@ t_value value_clone(t_value val) lst->len++; } } - return (res); + return (value_copy(res)); } static void list_drop(t_list *lst) @@ -64,10 +66,12 @@ static void list_drop(t_list *lst) void value_drop(t_value *value) { - if (value->tag == VALUE_BYTES) - arc_drop(value->val.v_bytes, noop); - else if (value->tag == VALUE_BYTES) + if (value->tag == VALUE_LIST) arc_drop(value->val.v_list, list_drop); + else if (value->tag == VALUE_BUILTIN) + arc_drop(value->val.v_builtin, value->val.v_builtin->drop); + else if (value->tag == VALUE_BYTES) + arc_drop(value->val.v_bytes, noop); } t_value value_unique(t_value *val) diff --git a/src/value_list.c b/src/value_list.c index 45d5588..2dc8ee0 100644 --- a/src/value_list.c +++ b/src/value_list.c @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/13 12:51:13 by agilliar #+# #+# */ -/* Updated: 2026/05/13 22:30:13 by agilliar ### ########.fr */ +/* Updated: 2026/05/18 12:47:53 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,12 +14,17 @@ #include "value.h" #include "panic.h" -// Borrows the value -t_value *value_list_get(t_value lst, size_t i) +size_t value_list_len(t_value lst) { if (lst.tag != VALUE_LIST) panic("List get on wrong type"); - if (lst.val.v_list->len <= i) + return (lst.val.v_list->len); +} + +// Borrows the value +t_value *value_list_get(t_value lst, size_t i) +{ + if (value_list_len(lst) <= i) panic("List get out of bounds"); return (&lst.val.v_list->buf[i]); } diff --git a/src/value_move.c b/src/value_move.c index 223208c..6007feb 100644 --- a/src/value_move.c +++ b/src/value_move.c @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/13 21:27:54 by agilliar #+# #+# */ -/* Updated: 2026/05/13 22:30:27 by agilliar ### ########.fr */ +/* Updated: 2026/05/18 11:55:04 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -31,3 +31,9 @@ t_value value_take_nil(t_value *a) { return (value_take(a, value_new_nil())); } + +void value_put(t_value *a, t_value b) +{ + value_swap(a, &b); + value_drop(&b); +} diff --git a/src/value_new.c b/src/value_new.c index 16b67aa..03bb098 100644 --- a/src/value_new.c +++ b/src/value_new.c @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/13 08:40:13 by agilliar #+# #+# */ -/* Updated: 2026/05/13 18:17:10 by agilliar ### ########.fr */ +/* Updated: 2026/05/18 14:56:45 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -38,13 +38,15 @@ t_value value_new_str(const char *s) return (res); } +// We could use arc_new_zeroed but clang and gcc cannot tell that the +// following zero writes for the nil values are no-ops t_value value_new_list(size_t len) { t_value res; size_t i; res.tag = VALUE_LIST; - res.val.v_list = arc_new_zeroed( + res.val.v_list = arc_new( uadd(sizeof(t_list), umul(sizeof(t_value), len))); res.val.v_list->len = len; i = 0; @@ -52,3 +54,16 @@ t_value value_new_list(size_t len) res.val.v_list->buf[i++] = value_new_nil(); return (res); } + +t_value value_new_builtin(t_value (*f)(t_value, t_value), + void *drop, size_t len) +{ + t_value res; + + res.tag = VALUE_BUILTIN; + res.val.v_list = arc_new( + uadd(sizeof(t_builtin), len)); + res.val.v_builtin->f = f; + res.val.v_builtin->drop = drop; + return (res); +} diff --git a/src/value_new.h b/src/value_new.h index 84fd3c1..5cb33f8 100644 --- a/src/value_new.h +++ b/src/value_new.h @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/13 22:05:40 by agilliar #+# #+# */ -/* Updated: 2026/05/13 22:06:22 by agilliar ### ########.fr */ +/* Updated: 2026/05/18 14:57:37 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -45,5 +45,7 @@ static inline t_value value_new_uint(uintptr_t n) t_value value_new_bytes(size_t len); t_value value_new_str(const char *s); t_value value_new_list(size_t len); +t_value value_new_builtin(t_value (*f)(t_value, t_value), + void *drop, size_t len); #endif diff --git a/src/value_types.h b/src/value_types.h index 5fe591e..9bb3481 100644 --- a/src/value_types.h +++ b/src/value_types.h @@ -6,15 +6,16 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/13 22:04:36 by agilliar #+# #+# */ -/* Updated: 2026/05/15 13:05:11 by agilliar ### ########.fr */ +/* Updated: 2026/05/18 14:57:06 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef VALUE_TYPES_H # define VALUE_TYPES_H -typedef struct s_bytes t_bytes; -typedef struct s_list t_list; +typedef struct s_bytes t_bytes; +typedef struct s_list t_list; +typedef struct s_builtin t_builtin; union u_value { @@ -22,6 +23,7 @@ union u_value intptr_t v_int; t_bytes *v_bytes; t_list *v_list; + t_builtin *v_builtin; }; enum e_value: uint8_t @@ -31,6 +33,7 @@ enum e_value: uint8_t VALUE_UINT, VALUE_BYTES, VALUE_LIST, + VALUE_BUILTIN, }; typedef struct s_value @@ -51,4 +54,12 @@ struct s_list t_value buf[]; }; +// F: self, arg -> res +struct s_builtin +{ + t_value (*f)(t_value, t_value); + void (*drop)(t_builtin *); + char buf[]; +}; + #endif diff --git a/test.c b/test.c index 21c539d..df2c8b7 100644 --- a/test.c +++ b/test.c @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/04/30 17:19:58 by agilliar #+# #+# */ -/* Updated: 2026/05/15 11:08:09 by agilliar ### ########.fr */ +/* Updated: 2026/05/18 15:03:08 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,6 +23,8 @@ void main2(void *_orig) char *s2 = malloc(strlen(orig) + 1); defer(free, s2); strcpy(s2, orig); + t_value res = expr_eval(builtin_noop(), value_new_uint(7)); + defer(value_drop, &res); printf("%s\n", s2); panic("error!"); printf("%s\n", s2); -- 2.53.0