${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_add.o: src/builtin_add.c src/builtin_register.h src/value_types.h \
+ src/value.h src/value_get.h src/panic.h src/jmp.h src/value_new.h \
+ src/defer.h src/framealloc.h src/align.h src/stacktrack.h \
+ src/memutils.h
${BUILDDIR}/builtin.o: src/builtin.c src/value.h src/value_get.h src/value_types.h \
src/panic.h src/jmp.h src/value_new.h
+${BUILDDIR}/builtin_list_get.o: src/builtin_list_get.c src/builtin_register.h \
+ src/value_types.h src/value.h src/value_get.h src/panic.h src/jmp.h \
+ src/value_new.h src/defer.h src/framealloc.h src/align.h \
+ src/stacktrack.h src/memutils.h
+${BUILDDIR}/builtin_list_set.o: src/builtin_list_set.c src/builtin_register.h \
+ src/value_types.h src/value.h src/value_get.h src/panic.h src/jmp.h \
+ src/value_new.h src/defer.h src/framealloc.h src/align.h \
+ src/stacktrack.h src/memutils.h
+${BUILDDIR}/builtin_list_set_drop.o: src/builtin_list_set_drop.c src/value.h \
+ src/value_get.h src/value_types.h src/panic.h src/jmp.h \
+ src/value_new.h src/arc.h src/memutils.h src/arith.h
${BUILDDIR}/builtin_mul.o: src/builtin_mul.c src/builtin_register.h src/value_types.h \
src/value.h src/value_get.h src/panic.h src/jmp.h src/value_new.h \
src/defer.h src/framealloc.h src/align.h src/stacktrack.h \
src/value_types.h
${BUILDDIR}/builtin_register.o: src/builtin_register.c src/builtin_register.h \
src/value_types.h
+${BUILDDIR}/builtin_sub.o: src/builtin_sub.c src/builtin_register.h src/value_types.h \
+ src/value.h src/value_get.h src/panic.h src/jmp.h src/value_new.h \
+ src/defer.h src/framealloc.h src/align.h src/stacktrack.h \
+ src/memutils.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 \
NAME=ccera.a
-SRCS=src/arc.c src/builtin.c src/builtin_mul.c src/builtin_noop.c src/builtin_register.c src/defer.c src/eval.c src/framealloc.c src/panic.c src/stacktrack.c src/value_debug.c src/value_lifetime.c src/value_list.c src/value_move.c src/value_new.c src/value_new_utils.c
+SRCS=src/arc.c src/builtin_add.c src/builtin.c src/builtin_list_get.c src/builtin_list_set.c src/builtin_list_set_drop.c src/builtin_mul.c src/builtin_noop.c src/builtin_register.c src/builtin_sub.c src/defer.c src/eval.c src/framealloc.c src/panic.c src/stacktrack.c src/value_debug.c src/value_lifetime.c src/value_list.c src/value_move.c src/value_new.c src/value_new_utils.c
HEADERS=src/align.h src/arc.h src/arith.h src/atomic.h src/builtin_register.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
-LTO=0
+#LTO=1
OPT=0
#CC=gcc
#UBSAN=1
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/05/13 08:56:53 by agilliar #+# #+# */
-/* Updated: 2026/05/18 14:43:36 by agilliar ### ########.fr */
+/* Updated: 2026/05/25 17:14:55 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
return ((void *) &res[1]);
}
-t_arc arc_new_zeroed(size_t size);
void noop(void *ptr);
#endif
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* builtin_add.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/05/25 14:49:44 by agilliar #+# #+# */
+/* Updated: 2026/05/25 14:50:50 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "builtin_register.h"
+#include "value.h"
+#include "defer.h"
+
+t_value builtin_iadd_impl(t_value self, t_value arg)
+{
+ t_value res;
+
+ (void) self;
+ errdefer(value_drop, &arg);
+ res = value_new_builtin(BUILTIN_IADD1);
+ res.val.v_int = *value_int(&arg);
+ return (res);
+}
+
+t_value builtin_iadd1_impl(t_value self, t_value arg)
+{
+ t_value res;
+
+ (void) self;
+ errdefer(value_drop, &arg);
+ res = value_new_int(*value_int(&arg));
+ __builtin_add_overflow(res.val.v_int,
+ self.val.v_int, &res.val.v_int);
+ return (res);
+}
+
+t_value builtin_uadd_impl(t_value self, t_value arg)
+{
+ t_value res;
+
+ (void) self;
+ errdefer(value_drop, &arg);
+ res = value_new_builtin(BUILTIN_UADD1);
+ res.val.v_uint = *value_uint(&arg);
+ return (res);
+}
+
+t_value builtin_uadd1_impl(t_value self, t_value arg)
+{
+ t_value res;
+
+ (void) self;
+ errdefer(value_drop, &arg);
+ res = value_new_uint(*value_uint(&arg));
+ __builtin_add_overflow(res.val.v_uint,
+ self.val.v_uint, &res.val.v_uint);
+ return (res);
+}
+
+__attribute__((constructor))
+void builtin_add_register(void)
+{
+ builtin_register(BUILTIN_IADD, &builtin_iadd_impl, "iadd");
+ builtin_register(BUILTIN_IADD1, &builtin_iadd1_impl, "iadd1");
+ builtin_register(BUILTIN_UADD, &builtin_uadd_impl, "uadd");
+ builtin_register(BUILTIN_UADD1, &builtin_uadd1_impl, "uadd1");
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* builtin_list_get.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/05/25 15:18:16 by agilliar #+# #+# */
+/* Updated: 2026/05/25 15:58:14 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "builtin_register.h"
+#include "value.h"
+#include "defer.h"
+
+t_value builtin_list_get_impl(t_value self, t_value arg)
+{
+ t_value res;
+
+ (void) self;
+ errdefer(value_drop, &arg);
+ res = value_new_builtin(BUILTIN_LIST_GET1);
+ res.val.v_uint = *value_uint(&arg);
+ return (res);
+}
+
+t_value builtin_list_get1_impl(t_value self, t_value arg)
+{
+ (void) self;
+ defer(value_drop, &arg);
+ return (value_copy(*value_list_get(arg, self.val.v_uint)));
+}
+
+__attribute__((constructor))
+void builtin_list_get_register(void)
+{
+ builtin_register(BUILTIN_LIST_GET, &builtin_list_get_impl, "list_get");
+ builtin_register(BUILTIN_LIST_GET1, &builtin_list_get1_impl, "list_get1");
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* builtin_list_set.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/05/25 16:25:55 by agilliar #+# #+# */
+/* Updated: 2026/05/25 17:33:13 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "builtin_register.h"
+#include "value.h"
+#include "defer.h"
+
+t_value builtin_list_set1_get_val(t_value val);
+void builtin_list_set1_drop(t_value *val);
+t_value builtin_list_set1_copy(t_value *val);
+
+t_value builtin_list_set_impl(t_value self, t_value arg)
+{
+ t_value res;
+
+ (void) self;
+ errdefer(value_drop, &arg);
+ res = value_new_builtin(BUILTIN_LIST_SET1);
+ res.val.v_uint = *value_uint(&arg);
+ return (res);
+}
+
+t_value builtin_list_set1_impl(t_value self, t_value arg)
+{
+ t_value *slot;
+ t_value res;
+
+ errdefer(value_drop, &arg);
+ slot = value_list_getu(&arg, self.val.v_uint);
+ value_put(slot, value_new_uint(self.val.v_uint));
+ res = value_new_builtin(BUILTIN_LIST_SET2);
+ res.val.v_ptr = slot;
+ return (res);
+}
+
+t_value builtin_list_set2_impl(t_value self, t_value arg)
+{
+ t_value res;
+
+ res = builtin_list_set1_get_val(self);
+ errdefer(value_drop, &self);
+ errdefer(value_drop, &arg);
+ value_put(value_list_getu(&res, *value_uint(self.val.v_ptr)), arg);
+ return (res);
+}
+
+__attribute__((constructor))
+void builtin_list_set_register(void)
+{
+ t_builtin *set1;
+
+ builtin_register(BUILTIN_LIST_SET, &builtin_list_set_impl, "list_set");
+ set1 = builtin_register(BUILTIN_LIST_SET1,
+ &builtin_list_set1_impl, "list_set1");
+ set1->drop = &builtin_list_set1_drop;
+ set1->copy = &builtin_list_set1_copy;
+ builtin_register(BUILTIN_LIST_SET2, &builtin_list_set2_impl, "list_set2");
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* builtin_list_set_drop.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/05/25 16:30:44 by agilliar #+# #+# */
+/* Updated: 2026/05/25 17:26:54 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "value.h"
+#include "arc.h"
+
+t_value builtin_list_set1_get_val(t_value val)
+{
+ t_value *slot;
+ uintptr_t i;
+ t_value res;
+
+ slot = val.val.v_ptr;
+ i = *value_uint(slot);
+ res.tag = VALUE_LIST;
+ res.val.v_list = (((void *) slot)
+ - sizeof(t_value) * i - offsetof(t_list, buf));
+ return (res);
+}
+
+void builtin_list_set1_drop(t_value *val)
+{
+ t_value lst;
+
+ lst = builtin_list_set1_get_val(*val);
+ value_drop(&lst);
+}
+
+t_value builtin_list_set1_copy(t_value *val)
+{
+ return (value_copy(builtin_list_set1_get_val(*val)));
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* builtin_sub.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/05/25 14:59:29 by agilliar #+# #+# */
+/* Updated: 2026/05/25 15:02:24 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "builtin_register.h"
+#include "value.h"
+#include "defer.h"
+
+t_value builtin_isub_impl(t_value self, t_value arg)
+{
+ t_value res;
+
+ (void) self;
+ errdefer(value_drop, &arg);
+ res = value_new_builtin(BUILTIN_ISUB1);
+ res.val.v_int = *value_int(&arg);
+ return (res);
+}
+
+t_value builtin_isub1_impl(t_value self, t_value arg)
+{
+ t_value res;
+
+ (void) self;
+ errdefer(value_drop, &arg);
+ res = value_new_int(*value_int(&arg));
+ __builtin_sub_overflow(self.val.v_int,
+ res.val.v_int, &res.val.v_int);
+ return (res);
+}
+
+t_value builtin_usub_impl(t_value self, t_value arg)
+{
+ t_value res;
+
+ (void) self;
+ errdefer(value_drop, &arg);
+ res = value_new_builtin(BUILTIN_USUB1);
+ res.val.v_uint = *value_uint(&arg);
+ return (res);
+}
+
+t_value builtin_usub1_impl(t_value self, t_value arg)
+{
+ t_value res;
+
+ (void) self;
+ errdefer(value_drop, &arg);
+ res = value_new_uint(*value_uint(&arg));
+ __builtin_sub_overflow(self.val.v_uint,
+ res.val.v_uint, &res.val.v_uint);
+ return (res);
+}
+
+__attribute__((constructor))
+void builtin_sub_register(void)
+{
+ builtin_register(BUILTIN_ISUB, &builtin_isub_impl, "isub");
+ builtin_register(BUILTIN_ISUB1, &builtin_isub1_impl, "isub1");
+ builtin_register(BUILTIN_USUB, &builtin_usub_impl, "usub");
+ builtin_register(BUILTIN_USUB1, &builtin_usub1_impl, "usub1");
+}
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/05/20 11:23:55 by agilliar #+# #+# */
-/* Updated: 2026/05/20 14:48:04 by agilliar ### ########.fr */
+/* Updated: 2026/05/25 18:13:32 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
value_debug_list(indent, value->val.v_list);
else if (value->tag == VALUE_NIL)
printf("%*s%s\n", (int)indent, "", "nil");
+ else if (value->tag == VALUE_BYTES)
+ printf("%*s%.*s\n", (int)indent, "", value->val.v_bytes->len,
+ value->val.v_bytes->buf);
else
printf("%*s%s\n", (int)indent, "", "<unknown>");
}
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/05/12 17:42:10 by agilliar #+# #+# */
-/* Updated: 2026/05/20 13:33:49 by agilliar ### ########.fr */
+/* Updated: 2026/05/25 17:52:28 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
t_list *lst;
res = val;
- if (val.tag == VALUE_LIST)
- {
+ if (val.tag == VALUE_BYTES)
res.val.v_bytes = arc_new(sizeof(t_bytes) + val.val.v_bytes->len);
+ if (val.tag == VALUE_BYTES)
cera_memcpy(res.val.v_bytes->buf, val.val.v_bytes->buf,
val.val.v_bytes->len);
- }
- else if (val.tag == VALUE_BYTES)
+ else if (val.tag == VALUE_LIST)
{
res.val.v_list = arc_new(sizeof(t_list)
+ sizeof(t_value) * val.val.v_list->len);
lst->len++;
}
}
- return (value_copy(res));
+ else
+ res = value_copy(res);
+ return (res);
}
static void list_drop(t_list *lst)
{
if ((val->tag == VALUE_BYTES && !arc_is_unique(val->val.v_bytes))
|| (val->tag == VALUE_LIST && !arc_is_unique(val->val.v_list)))
- *val = value_clone(*val);
+ value_put(val, value_clone(*val));
return (*val);
}
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/05/13 08:40:13 by agilliar #+# #+# */
-/* Updated: 2026/05/20 14:14:05 by agilliar ### ########.fr */
+/* Updated: 2026/05/25 18:14:32 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
len = cera_strlen(s);
res.val.v_bytes = arc_new(uadd(sizeof(t_bytes), len));
cera_memcpy(res.val.v_bytes->buf, s, len);
+ res.val.v_bytes->len = len;
return (res);
}
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/05/13 22:04:36 by agilliar #+# #+# */
-/* Updated: 2026/05/20 14:03:21 by agilliar ### ########.fr */
+/* Updated: 2026/05/25 16:39:10 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
intptr_t v_int;
t_bytes *v_bytes;
t_list *v_list;
+ void *v_ptr;
};
enum e_builtin: uint16_t
BUILTIN_ISUB1,
BUILTIN_USUB,
BUILTIN_USUB1,
+ BUILTIN_LIST_GET,
+ BUILTIN_LIST_GET1,
+ BUILTIN_LIST_SET,
+ BUILTIN_LIST_SET1,
+ BUILTIN_LIST_SET2,
_BUILTIN_MAX,
};
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/04/30 17:19:58 by agilliar #+# #+# */
-/* Updated: 2026/05/20 15:33:15 by agilliar ### ########.fr */
+/* Updated: 2026/05/27 13:23:35 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
#include <stdio.h>
#include <stdlib.h>
-t_value test_expr(void)
+// a -> b -> a
+t_value value_true(void)
{
- t_value exprs = value_new_va(
+ t_value res = value_new_va(
+ 4,
+ value_new_builtin(BUILTIN_NOOP),
+ value_new_nil(),
+ value_new_nil(),
+ value_new_step(0, false, 1, false)
+ );
+ return (value_new_va(2, res, value_new_uint(1)));
+}
+
+// a -> b -> b
+t_value value_false(void)
+{
+ t_value res = value_new_va(
+ 4,
+ value_new_builtin(BUILTIN_NOOP),
+ value_new_nil(),
+ value_new_nil(),
+ value_new_step(0, false, 2, false)
+ );
+ return (value_new_va(2, res, value_new_uint(1)));
+}
+
+// bool -> a -> b -> a | b
+t_value ite(void)
+{
+ t_value res = value_new_va(
5,
- value_new_builtin(BUILTIN_UMUL),
- value_new_uint(8),
+ value_new_builtin(BUILTIN_LIST_GET),
+ value_new_va(2, value_false(), value_true()),
+ value_new_nil(),
+ value_new_step(0, true, 2, true),
+ value_new_step(3, true, 1, true)
+ );
+ return (value_new_va(2, res, value_new_uint(2)));
+}
+
+// (a -> b) -> a -> nil -> b
+t_value lazy_eval(void)
+{
+ t_value res = value_new_va(
+ 4,
+ value_new_nil(),
+ value_new_nil(),
+ value_new_nil(),
+ value_new_step(0, true, 1, true)
+ );
+ return (value_new_va(2, res, value_new_uint(0)));
+}
+
+// (a -> b) -> (b -> c) -> a -> c
+t_value compose(void)
+{
+ t_value res = value_new_va(
+ 5,
+ value_new_nil(),
+ value_new_nil(),
+ value_new_nil(),
+ value_new_step(0, true, 2, true),
+ value_new_step(3, true, 1, true)
+ );
+ return (value_new_va(2, res, value_new_uint(0)));
+}
+
+
+// (f: f -> a) -> a
+t_value make_rec(void)
+{
+ t_value comb = value_new_va(
+ 2,
+ value_new_nil(),
+ value_new_step(0, false, 0, true)
+ );
+ return (value_new_va(2, comb, value_new_uint(0)));
+}
+
+/*
+t_value fib(void)
+{
+ t_value comb = value_new_va(
+ _,
+ make_rec(),
+ ite(),
+ value_new_builtin(BUILTIN_UADD),
+ value_new_builtin(BUILTIN_NOOP),
+ value_new_nil(),
+ value_new_nil(),
+ value_new_nil(),
+ );
+ return (expr_eval(make_rec(), value_new_va(2, comb, value_new_uint(0))));
+}
+*/
+
+t_value test_expr(void)
+{
+ t_value exprs = value_new_va(
+ 7,
+ ite(),
+ value_new_uint(100),
+ value_new_uint(103),
value_new_nil(),
- value_new_step(0, false, 1, true),
- value_new_step(3, false, 2, true)
+ value_new_step(0, true, 3, true),
+ value_new_step(4, true, 1, true),
+ value_new_step(5, true, 2, true)
);
- return (value_new_va(2, exprs, value_new_uint(2)));
+ return (value_new_va(2, exprs, value_new_uint(3)));
}
void main2(void *_orig)
char *s2 = malloc(strlen(orig) + 1);
defer(free, s2);
strcpy(s2, orig);
- t_value res = expr_eval(test_expr(), value_new_uint(7));
+ t_value res = expr_eval(test_expr(), value_new_uint(0));
+ //t_value res = expr_eval(fib(), value_new_uint(10));
value_debug(0, &res);
defer(value_drop, &res);
printf("%s\n", s2);