-[*]
+[*.{c,h}]
+indent_style = tab
+
+[Makefile]
indent_style = tab
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
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
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
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <stdint.h>
+# include <stddef.h>
# 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);
}
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <stddef.h>
#include "arc.h"
#include "panic.h"
-#include <stdlib.h>
+#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]);
}
// 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);
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)
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <stdint.h>
+# include <stddef.h>
# include <stdbool.h>
+# 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
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
/* */
/* ************************************************************************** */
# 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");
}
__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");
}
__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");
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <stdint.h>
-# include <stdbool.h>
-# include <stddef.h>
-
# include "jmp.h"
# include "defer.h"
# include "panic.h"
// 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
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
/* */
/* ************************************************************************** */
# include <string.h>
# include "framealloc.h"
# include "return_patch.h"
+# include "memutils.h"
typedef struct s_defer
{
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
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <stdlib.h>
+
+// 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)));
+}
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <stdint.h>
+# include <stddef.h>
# include "return_patch.h"
# include "align.h"
typedef struct s_framealloc_frame
{
- uintptr_t used;
+ size_t used;
struct s_framealloc_frame *prev;
void *ret_ptr;
void *frame_ptr;
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);
}
__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));
}
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <stdint.h>
+# include <stddef.h>
-typedef intptr_t t_jmp[3];
+typedef size_t t_jmp[3];
#endif
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* memutils.h :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* 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 <stddef.h>
+# include <stdlib.h>
+# 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
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
/* */
/* ************************************************************************** */
return (&store);
}
+__attribute__((returns_nonnull))
void *catch(void *f, void *dat)
{
void *res;
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
/* */
/* ************************************************************************** */
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
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* stacktrack.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/05/14 12:00:36 by agilliar #+# #+# */
+/* Updated: 2026/05/14 13:11:24 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#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)--;
+}
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <stddef.h>
# include <stdint.h>
-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
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* value_get.h :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* 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
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <stddef.h>
#include "arc.h"
#include "defer.h"
#include "value.h"
-#include <string.h>
+#include "memutils.h"
t_value value_copy(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)
+ 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]);
static void list_drop(t_list *lst)
{
- uintptr_t i;
+ size_t i;
i = 0;
while (i < lst->len)
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* value_list.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/05/13 12:51:13 by agilliar #+# #+# */
+/* Updated: 2026/05/13 22:30:13 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include <stddef.h>
+#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));
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* value_move.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* 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()));
+}
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <stddef.h>
#include "value.h"
#include "arith.h"
#include "arc.h"
-#include <string.h>
+#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);
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* value_new.h :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* 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
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* value_types.h :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* 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