From: Axy Date: Thu, 14 May 2026 11:16:41 +0000 (+0200) Subject: Borked but about to make big changes X-Git-Url: https://git.uwuaxy.net/?a=commitdiff_plain;h=a0c866c4e0aa4bd7cc29d811c9c56042f57e0f45;p=axy%2Fft%2Fc-cera.git Borked but about to make big changes --- diff --git a/.editorconfig b/.editorconfig index 0b225af..5643d90 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,2 +1,5 @@ -[*] +[*.{c,h}] +indent_style = tab + +[Makefile] indent_style = tab diff --git a/Makefile b/Makefile index 8673653..6f1899c 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ NAME=ccera.a -SRCS=src/arc.c src/defer.c src/eval.c src/framealloc.c src/panic.c src/value_lifetime.c src/value_new.c +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 -HEADERS=src/align.h src/arc.h src/arith.h src/ccera.h src/defer.h src/framealloc.h src/jmp.h src/panic.h src/return_patch.h src/value.h +HEADERS=src/align.h src/arc.h src/arith.h src/ccera.h src/defer.h src/framealloc.h src/jmp.h src/memutils.h src/panic.h src/return_patch.h src/value_get.h src/value.h src/value_new.h src/value_types.h BUILDDIR=.build @@ -13,9 +13,12 @@ DEPSFILE=.deps OBJS=${SRCS:src/%.c=${BUILDDIR}/%.o} CFLAGS=-Wall -Wextra -Werror -pthread -std=gnu23 +# IMPORTANT: We use this to properly keep track of stack frames at a source level +CFLAGS += -finstrument-functions CFLAGS += -g -#CFLAGS += -O3 -#CFLAGS += -flto -ffat-lto-objects +CFLAGS += -O3 +CFLAGS += -flto -ffat-lto-objects +CFLAGS += -fdiagnostics-color #CC=clang CC=gcc @@ -46,13 +49,13 @@ fclean: clean re: fclean all -${THIS}.tmp: ${SRCS} ${HEADERS} ${THIS} +${THIS}.tmp: src ${THIS} @sed "s?^SRCS=.*?$$(echo -n SRCS=; echo -n src/*.c)?" ${THIS} \ | sed "s?^HEADERS=.*?$$(echo -n HEADERS=; echo -n src/*.h)?" \ > ${THIS}.tmp -${DEPSFILE}.tmp: ${SRCS} ${HEADERS} ${THIS} - ${CC} -MM ${SRCS} | sed "s/^\([^ ]\)/\$${BUILDDIR}\/\1/" > $@ +${DEPSFILE}.tmp: src ${THIS} + ${CC} ${CFLAGS} -MM ${SRCS} | sed "s/^\([^ ]\)/\$${BUILDDIR}\/\1/" > $@ redeps: ${DEPSFILE}.tmp @echo Rebuilding deps diff --git a/src/align.h b/src/align.h index 371cd30..05f9b39 100644 --- a/src/align.h +++ b/src/align.h @@ -6,34 +6,52 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/12 10:03:30 by agilliar #+# #+# */ -/* Updated: 2026/05/12 13:36:28 by agilliar ### ########.fr */ +/* Updated: 2026/05/13 21:16:36 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef ALIGN_H # define ALIGN_H -# include +# include # ifdef __builtin_align_up __attribute__((always_inline)) -static inline void *align_up(void *p, uintptr_t align) +static inline void *align_up(void *p, size_t align) { return (__builtin_align_up(p, align)); } +__attribute__((always_inline)) +static inline void *align_down(void *p, size_t align) +{ + return (__builtin_align_down(p, align)); +} + # else __attribute__((always_inline)) -static inline void *align_up(void *p, uintptr_t align) +static inline void *align_up(void *p, size_t align) +{ + size_t n; + + n = (size_t) p; + n += align - 1; + n = (n / align) * align; + n -= (size_t) p; + p = &((char *) p)[n]; + return (p); +} + +__attribute__((always_inline)) +static inline void *align_down(void *p, size_t align) { - uintptr_t n; + size_t n; - n = (intptr_t) p; - if (n % align) - n = ((n / align) + n % align) * align; - n -= (intptr_t) p; + n = (size_t) p; + n = (n / align) * align; + n -= (size_t) p; p = &((char *) p)[n]; return (p); } diff --git a/src/arc.c b/src/arc.c index 83329fd..76bbaed 100644 --- a/src/arc.c +++ b/src/arc.c @@ -6,23 +6,21 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/04/29 16:40:27 by agilliar #+# #+# */ -/* Updated: 2026/05/13 09:00:47 by agilliar ### ########.fr */ +/* Updated: 2026/05/13 16:42:04 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ +#include #include "arc.h" #include "panic.h" -#include +#include "memutils.h" +#include "arith.h" -t_arc arc_new(uintptr_t size) +t_arc arc_new(size_t size) { - uintptr_t *res; + size_t *res; - if (__builtin_add_overflow(size, sizeof(uintptr_t), &size)) - panic("Arc alloc too big to create"); - res = malloc(size); - if (!res) - panic("Malloc failed while creating arc"); + res = cera_malloc(uadd(sizeof(size_t), size)); res[0] = 1; return ((void *) &res[1]); } @@ -30,17 +28,17 @@ t_arc arc_new(uintptr_t size) // Relaxed sub as we own a copy, and as such ultimately sync void arc_copy(t_arc arc) { - if (__atomic_add_fetch(((uintptr_t *)arc) - 1, 1, __ATOMIC_RELAXED) - >= ((uintptr_t) 1) << (sizeof(uintptr_t) * 8 - 1)) + if (__atomic_add_fetch(((size_t *)arc) - 1, 1, __ATOMIC_RELAXED) + >= ((size_t) 1) << (sizeof(size_t) * 8 - 1)) { - __atomic_sub_fetch(((uintptr_t *)arc) - 1, 1, __ATOMIC_RELAXED); + __atomic_sub_fetch(((size_t *)arc) - 1, 1, __ATOMIC_RELAXED); panic("Arc counter near overflowing"); } } void arc_drop(t_arc arc, t_drop destructor) { - if (__atomic_sub_fetch(((uintptr_t *)arc) - 1, 1, __ATOMIC_RELEASE) != 0) + if (__atomic_sub_fetch(((size_t *)arc) - 1, 1, __ATOMIC_RELEASE) != 0) return ; __atomic_thread_fence(__ATOMIC_ACQUIRE); ((void (*)(void *))destructor)(arc); @@ -49,7 +47,7 @@ void arc_drop(t_arc arc, t_drop destructor) bool arc_is_unique(t_arc arc) { - return (__atomic_load_n(((uintptr_t *)arc) - 1, __ATOMIC_ACQUIRE) == 1); + return (__atomic_load_n(((size_t *)arc) - 1, __ATOMIC_ACQUIRE) == 1); } void noop(void *ptr) diff --git a/src/arc.h b/src/arc.h index 600dca1..5ca8a82 100644 --- a/src/arc.h +++ b/src/arc.h @@ -6,24 +6,37 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/13 08:56:53 by agilliar #+# #+# */ -/* Updated: 2026/05/13 10:02:51 by agilliar ### ########.fr */ +/* Updated: 2026/05/13 12:55:03 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef ARC_H # define ARC_H -# include +# include # include +# include "memutils.h" +# include "arith.h" typedef void *t_arc; typedef void *t_drop; -t_arc arc_new(uintptr_t size); +t_arc arc_new(size_t size); void arc_copy(t_arc arc); void arc_drop(t_arc arc, t_drop destructor); bool arc_is_unique(t_arc arc); +__attribute__((always_inline)) +static inline t_arc arc_new_zeroed(size_t size) +{ + size_t *res; + + res = cera_calloc(uadd(sizeof(size_t), size)); + res[0] = 1; + return ((void *) &res[1]); +} + +t_arc arc_new_zeroed(size_t size); void noop(void *ptr); #endif diff --git a/src/arith.h b/src/arith.h index baccaa5..cc86cc5 100644 --- a/src/arith.h +++ b/src/arith.h @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/13 08:42:44 by agilliar #+# #+# */ -/* Updated: 2026/05/13 08:54:14 by agilliar ### ########.fr */ +/* Updated: 2026/05/13 11:59:31 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,7 +17,7 @@ # include "panic.h" __attribute__((always_inline)) -static inline uintptr_t uadd(uintptr_t a, uintptr_t b) +static inline uint64_t uadd(uint64_t a, uint64_t b) { if (__builtin_add_overflow(a, b, &a)) panic("Addition overflowed"); @@ -25,7 +25,7 @@ static inline uintptr_t uadd(uintptr_t a, uintptr_t b) } __attribute__((always_inline)) -static inline uintptr_t usub(uintptr_t a, uintptr_t b) +static inline uint64_t usub(uint64_t a, uint64_t b) { if (__builtin_sub_overflow(a, b, &a)) panic("Substraction overflowed"); @@ -33,7 +33,7 @@ static inline uintptr_t usub(uintptr_t a, uintptr_t b) } __attribute__((always_inline)) -static inline uintptr_t umul(uintptr_t a, uintptr_t b) +static inline uint64_t umul(uint64_t a, uint64_t b) { if (__builtin_mul_overflow(a, b, &a)) panic("Multiplication overflowed"); diff --git a/src/ccera.h b/src/ccera.h index edaab42..01226ed 100644 --- a/src/ccera.h +++ b/src/ccera.h @@ -6,17 +6,13 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/04/29 16:08:57 by agilliar #+# #+# */ -/* Updated: 2026/05/13 08:57:19 by agilliar ### ########.fr */ +/* Updated: 2026/05/13 21:17:24 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef CCERA_H # define CCERA_H -# include -# include -# include - # include "jmp.h" # include "defer.h" # include "panic.h" @@ -43,6 +39,6 @@ // 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 val); #endif diff --git a/src/defer.h b/src/defer.h index b3a272b..c15bad1 100644 --- a/src/defer.h +++ b/src/defer.h @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/10 22:08:53 by agilliar #+# #+# */ -/* Updated: 2026/05/12 16:58:46 by agilliar ### ########.fr */ +/* Updated: 2026/05/13 20:54:16 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,6 +17,7 @@ # include # include "framealloc.h" # include "return_patch.h" +# include "memutils.h" typedef struct s_defer { @@ -88,24 +89,19 @@ static inline void errdefer(void *f, void *dat) defer_store()->frame = curr; } +// Defers the given function, alloca-ing size data from the pointer +// Not necessary for errdefer as the stack variables are still live +// on panic +// __attribute__((always_inline)) -static inline void deferc(void *f, void *dat, uintptr_t size) +static inline void *deferc(void *f, void *dat, size_t size) { void *b; b = cera_alloca(size); - memcpy(b, dat, size); + cera_memcpy(b, dat, size); defer(f, b); -} - -__attribute__((always_inline)) -static inline void errdeferc(void *f, void *dat, uintptr_t size) -{ - void *b; - - b = cera_alloca(size); - memcpy(b, dat, size); - errdefer(f, b); + return (b); } #endif diff --git a/src/eval.c b/src/eval.c index 2636220..90499ce 100644 --- a/src/eval.c +++ b/src/eval.c @@ -6,9 +6,57 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/04 01:21:34 by agilliar #+# #+# */ -/* Updated: 2026/05/05 05:31:52 by agilliar ### ########.fr */ +/* Updated: 2026/05/13 22:42:06 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ #include "ccera.h" -#include + +// Has ownership of the values given +t_value eval_step(t_value arg, t_value *exprs, uintptr_t *i) +{ + (void) arg; + (void) exprs; + (void) i; +} + +// 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)*), +// current_pos +// ) +// The nil values are considered to have been moved out, and it is an error for +// them to be used +// The nil expressions are locations where an argument is expected, halting +// evaluation +// An expression is as follows: +// (eval_idx, arg_idx, 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; + t_value *eval; + t_value arg; + t_value *exprs; + uintptr_t *i; + + expr = deferc(value_drop, &_expr, sizeof(t_value)); + 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) + { + eval_step(arg, exprs, i); + (*i)++; + } + return (value_take_nil(value_list_getu(eval, (*i) - 1))); +} diff --git a/src/framealloc.h b/src/framealloc.h index 2538eea..a176e8f 100644 --- a/src/framealloc.h +++ b/src/framealloc.h @@ -6,14 +6,14 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/11 19:17:56 by agilliar #+# #+# */ -/* Updated: 2026/05/12 16:58:56 by agilliar ### ########.fr */ +/* Updated: 2026/05/13 21:16:13 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef FRAMEALLOC_H # define FRAMEALLOC_H -# include +# include # include "return_patch.h" # include "align.h" @@ -23,7 +23,7 @@ typedef struct s_framealloc_frame { - uintptr_t used; + size_t used; struct s_framealloc_frame *prev; void *ret_ptr; void *frame_ptr; @@ -41,14 +41,14 @@ void framealloc_pop_shim(void) void framealloc_pop(void); __attribute__((always_inline, malloc, alloc_size(1), alloc_align(2))) -static inline void *cera_alloca_align_nopatch(uintptr_t len, uintptr_t align) +static inline void *cera_alloca_align_nopatch(size_t len, size_t align) { t_framealloc *store; void *res; store = framealloc_store(); res = &store->buf[store->frame.used]; - store->frame.used += ((uintptr_t)(align_up(res, align) - res)) + store->frame.used += ((size_t)(align_up(res, align) - res)) + len; res = align_up(res, align); return (res); @@ -78,14 +78,14 @@ static inline void cera_alloca_patch(void) } __attribute__((always_inline, malloc, alloc_size(1), alloc_align(2))) -static inline void *cera_alloca_align(uintptr_t len, uintptr_t align) +static inline void *cera_alloca_align(size_t len, size_t align) { cera_alloca_patch(); return (cera_alloca_align_nopatch(len, align)); } __attribute__((always_inline, malloc, alloc_size(1))) -static inline void *cera_alloca(uintptr_t len) +static inline void *cera_alloca(size_t len) { return (cera_alloca_align(len, 8)); } diff --git a/src/jmp.h b/src/jmp.h index 45c24a5..0d42250 100644 --- a/src/jmp.h +++ b/src/jmp.h @@ -6,15 +6,16 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/10 22:08:02 by agilliar #+# #+# */ -/* Updated: 2026/05/13 10:53:39 by agilliar ### ########.fr */ +/* Updated: 2026/05/13 16:43:56 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef JMP_H + # define JMP_H -# include +# include -typedef intptr_t t_jmp[3]; +typedef size_t t_jmp[3]; #endif diff --git a/src/memutils.h b/src/memutils.h new file mode 100644 index 0000000..18acaaa --- /dev/null +++ b/src/memutils.h @@ -0,0 +1,74 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* memutils.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/05/13 11:08:38 by agilliar #+# #+# */ +/* Updated: 2026/05/13 12:28:33 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef MEMUTILS_H +# define MEMUTILS_H + +# include +# include +# include "panic.h" + +__attribute__((always_inline)) +static inline void + *cera_memcpy(void *restrict dst, const void *src, size_t len) +{ + size_t i; + + i = 0; + while (i < len) + { + ((char *restrict) dst)[i] = ((const char *) src)[i]; + i++; + } + return (dst); +} + +__attribute__((always_inline)) +static inline void *cera_memset(void *dst, char c, size_t len) +{ + size_t i; + + i = 0; + while (i < len) + ((char *) dst)[i++] = c; + return (dst); +} + +__attribute__((always_inline)) +static inline size_t cera_strlen(const char *dst) +{ + size_t i; + + i = 0; + while (dst[i] != '\0') + i++; + return (i); +} + +__attribute__((always_inline)) +static inline void *cera_malloc(size_t len) +{ + void *res; + + res = malloc(len); + if (!res) + panic("Malloc error"); + return (res); +} + +__attribute__((always_inline)) +static inline void *cera_calloc(size_t len) +{ + return (cera_memset(cera_malloc(len), 0, len)); +} + +#endif diff --git a/src/panic.c b/src/panic.c index f3e0640..699db6f 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/13 09:36:19 by agilliar ### ########.fr */ +/* Updated: 2026/05/13 11:34:46 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,6 +20,7 @@ t_panic_info *panic_store(void) return (&store); } +__attribute__((returns_nonnull)) void *catch(void *f, void *dat) { void *res; diff --git a/src/panic.h b/src/panic.h index 213fbf5..85f7d07 100644 --- a/src/panic.h +++ b/src/panic.h @@ -6,7 +6,7 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/10 22:11:10 by agilliar #+# #+# */ -/* Updated: 2026/05/12 12:16:56 by agilliar ### ########.fr */ +/* Updated: 2026/05/13 11:34:25 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ @@ -26,7 +26,8 @@ t_panic_info *panic_store(void); void panic(void *err) __attribute__((noreturn, nonnull(1))); -void *catch(void *f, void *dat); +void *catch(void *f, void *dat) + __attribute__((returns_nonnull)); bool panicking(void); #endif diff --git a/src/stacktrack.c b/src/stacktrack.c new file mode 100644 index 0000000..b948404 --- /dev/null +++ b/src/stacktrack.c @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* stacktrack.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/05/14 12:00:36 by agilliar #+# #+# */ +/* Updated: 2026/05/14 13:11:24 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include + +#define RETFUNC_STACK_HEIGHT 1024 + +void ***retfunc_store(void) +{ + static __thread void *stack[RETFUNC_STACK_HEIGHT]; + static __thread void **store = stack; + + return (&store); +} + +__attribute__((no_instrument_function)) +void __cyg_profile_func_enter(void *this_fn, void *call_site) +{ + void **store; + + (void) this_fn; + (void) call_site; + store = retfunc_store(); + (*store)++; + if (**store) + __builtin_unreachable(); +} + +__attribute__((no_instrument_function)) +void __cyg_profile_func_exit(void *this_fn, void *call_site) +{ + void **store; + + (void) this_fn; + (void) call_site; + store = retfunc_store(); + if (**store) + ((void (*)(void))**store)(); + **store = NULL; + (*store)--; +} diff --git a/src/value.h b/src/value.h index 458f6dc..9c2cc85 100644 --- a/src/value.h +++ b/src/value.h @@ -6,55 +6,30 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/12 16:14:16 by agilliar #+# #+# */ -/* Updated: 2026/05/13 09:08:29 by agilliar ### ########.fr */ +/* Updated: 2026/05/13 22:20:49 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef VALUE_H # define VALUE_H +# include # include -typedef struct s_bytes t_bytes; -typedef struct s_list t_list; - -union u_value -{ - intptr_t v_int; - uintptr_t v_uint; - t_bytes *v_bytes; - t_list *v_list; -}; - -enum e_value: uint8_t -{ - VALUE_UNDEF, - VALUE_INT, - VALUE_UINT, - VALUE_BYTES, - VALUE_LIST, -}; - -typedef struct s_value -{ - union u_value val; - enum e_value tag; -} t_value; - -typedef struct s_bytes -{ - uintptr_t len; - uint8_t buf[]; -} t_bytes; - -typedef struct s_list -{ - uintptr_t len; - t_value buf[]; -} t_list; +# include "value_get.h" +# include "value_types.h" +# include "value_new.h" t_value value_copy(t_value val); t_value value_clone(t_value val); void value_drop(t_value *value); +t_value value_unique(t_value *val); + +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); #endif diff --git a/src/value_get.h b/src/value_get.h new file mode 100644 index 0000000..a33c66f --- /dev/null +++ b/src/value_get.h @@ -0,0 +1,51 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* value_get.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/05/13 22:01:24 by agilliar #+# #+# */ +/* Updated: 2026/05/13 22:29:29 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef VALUE_GET_H +# define VALUE_GET_H + +# include "value_types.h" +# include "panic.h" + +__attribute__((always_inline)) +static inline intptr_t *value_int(t_value *value) +{ + if (value->tag != VALUE_INT) + panic("Expected value to be int"); + return (&value->val.v_int); +} + +__attribute__((always_inline)) +static inline uintptr_t *value_uint(t_value *value) +{ + if (value->tag != VALUE_UINT) + panic("Expected value to be uint"); + return (&value->val.v_uint); +} + +__attribute__((always_inline)) +static inline t_list *value_list(t_value *value) +{ + if (value->tag != VALUE_LIST) + panic("Expected value to be list"); + return (value->val.v_list); +} + +__attribute__((always_inline)) +static inline t_bytes *value_bytes(t_value *value) +{ + if (value->tag != VALUE_BYTES) + panic("Expected value to be bytes"); + return (value->val.v_bytes); +} + +#endif diff --git a/src/value_lifetime.c b/src/value_lifetime.c index 2bbf6e4..d37290f 100644 --- a/src/value_lifetime.c +++ b/src/value_lifetime.c @@ -6,14 +6,15 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/12 17:42:10 by agilliar #+# #+# */ -/* Updated: 2026/05/13 09:36:40 by agilliar ### ########.fr */ +/* Updated: 2026/05/13 22:29:20 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ +#include #include "arc.h" #include "defer.h" #include "value.h" -#include +#include "memutils.h" t_value value_copy(t_value val) { @@ -33,7 +34,7 @@ t_value value_clone(t_value val) if (val.tag == VALUE_LIST) { res.val.v_bytes = arc_new(sizeof(t_bytes) + val.val.v_bytes->len); - memcpy(res.val.v_bytes->buf, val.val.v_bytes->buf, + cera_memcpy(res.val.v_bytes->buf, val.val.v_bytes->buf, val.val.v_bytes->len); } else if (val.tag == VALUE_BYTES) @@ -42,7 +43,7 @@ t_value value_clone(t_value val) + sizeof(t_value) * val.val.v_list->len); lst = res.val.v_list; lst->len = 0; - errdeferc(value_drop, &res, sizeof(t_value)); + errdefer(value_drop, &res); while (lst->len < val.val.v_list->len) { lst->buf[lst->len] = value_copy(val.val.v_list->buf[lst->len]); @@ -54,7 +55,7 @@ t_value value_clone(t_value val) static void list_drop(t_list *lst) { - uintptr_t i; + size_t i; i = 0; while (i < lst->len) diff --git a/src/value_list.c b/src/value_list.c new file mode 100644 index 0000000..45d5588 --- /dev/null +++ b/src/value_list.c @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* value_list.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/05/13 12:51:13 by agilliar #+# #+# */ +/* Updated: 2026/05/13 22:30:13 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include +#include "value.h" +#include "panic.h" + +// Borrows the value +t_value *value_list_get(t_value lst, size_t i) +{ + if (lst.tag != VALUE_LIST) + panic("List get on wrong type"); + if (lst.val.v_list->len <= i) + panic("List get out of bounds"); + return (&lst.val.v_list->buf[i]); +} + +t_value *value_list_getu(t_value *lst, size_t i) +{ + value_unique(lst); + return (value_list_get(*lst, i)); +} diff --git a/src/value_move.c b/src/value_move.c new file mode 100644 index 0000000..223208c --- /dev/null +++ b/src/value_move.c @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* value_move.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/05/13 21:27:54 by agilliar #+# #+# */ +/* Updated: 2026/05/13 22:30:27 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "value.h" + +void value_swap(t_value *a, t_value *b) +{ + t_value tmp; + + tmp = *a; + *a = *b; + *b = tmp; +} + +t_value value_take(t_value *a, t_value b) +{ + value_swap(a, &b); + return (b); +} + +t_value value_take_nil(t_value *a) +{ + return (value_take(a, value_new_nil())); +} diff --git a/src/value_new.c b/src/value_new.c index cbf9f29..16b67aa 100644 --- a/src/value_new.c +++ b/src/value_new.c @@ -6,21 +6,49 @@ /* By: agilliar +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/13 08:40:13 by agilliar #+# #+# */ -/* Updated: 2026/05/13 09:02:48 by agilliar ### ########.fr */ +/* Updated: 2026/05/13 18:17:10 by agilliar ### ########.fr */ /* */ /* ************************************************************************** */ +#include #include "value.h" #include "arith.h" #include "arc.h" -#include +#include "memutils.h" -t_value value_new_bytes(uintptr_t len) +t_value value_new_bytes(size_t len) { t_value res; res.tag = VALUE_BYTES; - res.val.v_bytes = arc_new(uadd(sizeof(t_bytes), len)); + res.val.v_bytes = arc_new_zeroed(uadd(sizeof(t_bytes), len)); res.val.v_bytes->len = len; return (res); } + +t_value value_new_str(const char *s) +{ + t_value res; + size_t len; + + res.tag = VALUE_BYTES; + len = cera_strlen(s); + res.val.v_bytes = arc_new(uadd(sizeof(t_bytes), len)); + cera_memcpy(res.val.v_bytes->buf, s, len); + return (res); +} + +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( + uadd(sizeof(t_list), umul(sizeof(t_value), len))); + res.val.v_list->len = len; + i = 0; + while (i < len) + res.val.v_list->buf[i++] = value_new_nil(); + return (res); +} diff --git a/src/value_new.h b/src/value_new.h new file mode 100644 index 0000000..84fd3c1 --- /dev/null +++ b/src/value_new.h @@ -0,0 +1,49 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* value_new.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/05/13 22:05:40 by agilliar #+# #+# */ +/* Updated: 2026/05/13 22:06:22 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef VALUE_NEW_H +# define VALUE_NEW_H + +__attribute__((always_inline)) +static inline t_value value_new_nil(void) +{ + t_value res; + + res.tag = VALUE_NIL; + return (res); +} + +__attribute__((always_inline)) +static inline t_value value_new_int(intptr_t n) +{ + t_value res; + + res.tag = VALUE_INT; + res.val.v_int = n; + return (res); +} + +__attribute__((always_inline)) +static inline t_value value_new_uint(uintptr_t n) +{ + t_value res; + + res.tag = VALUE_UINT; + res.val.v_uint = n; + return (res); +} + +t_value value_new_bytes(size_t len); +t_value value_new_str(const char *s); +t_value value_new_list(size_t len); + +#endif diff --git a/src/value_types.h b/src/value_types.h new file mode 100644 index 0000000..a80c8c7 --- /dev/null +++ b/src/value_types.h @@ -0,0 +1,54 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* value_types.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/05/13 22:04:36 by agilliar #+# #+# */ +/* Updated: 2026/05/13 22:08:57 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef VALUE_TYPES_H +# define VALUE_TYPES_H + +typedef struct s_bytes t_bytes; +typedef struct s_list t_list; + +union u_value +{ + uintptr_t v_uint; + intptr_t v_int; + t_bytes *v_bytes; + t_list *v_list; +}; + +enum e_value: uint8_t +{ + VALUE_NIL, + VALUE_INT, + VALUE_UINT, + VALUE_BYTES, + VALUE_LIST, +}; + +typedef struct s_value +{ + union u_value val; + enum e_value tag; +} t_value; + +typedef struct s_bytes +{ + size_t len; + char buf[]; +} t_bytes; + +typedef struct s_list +{ + size_t len; + t_value buf[]; +} t_list; + +#endif