.build
*.a
.norm
+a.out
+a.out
NAME=ccera.a
-SRCS=src/arc.c src/value_get.c src/value_new.c
+SRCS=src/arc.c src/eval.c src/value_destroy.c src/value_get.c src/value_lifetime.c src/value_new.c
HEADERS=src/ccera.h
OBJS=${SRCS:src/%.c=${BUILDDIR}/%.o}
-CFLAGS=-Wall -Wextra -Werror -g -pthread -O3
+CFLAGS=-Wall -Wextra -Werror -g -pthread -flto -ffat-lto-objects
+#CFLAGS=-Wall -Wextra -Werror -g -pthread -O3 -flto -ffat-lto-objects
-CC=cc
+CC=gcc
+
+AR=ar
MAKEFLAGS += --no-print-directory
all : ${NAME}
-${BUILDDIR}/%.o : src/%.c ${HEADERS} | ${BUILDDIR}
+${BUILDDIR}/%.o : src/%.c ${HEADERS} ${THIS} | ${BUILDDIR}
${CC} ${CFLAGS} -c -o $@ $<
${BUILDDIR} :
mkdir ${BUILDDIR}
-${NAME} : ${OBJS}
- ar rcs $@ $^
+${NAME} : ${OBJS} ${THIS}
+ ${AR} rcs $@ ${OBJS}
clean :
rm -f ${OBJS}
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/04/29 16:40:27 by agilliar #+# #+# */
-/* Updated: 2026/04/30 15:04:33 by agilliar ### ########.fr */
+/* Updated: 2026/05/04 02:01:19 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
return (NULL);
}
-void arc_destroy(t_arc arc, void (*destructor)(void *))
+void arc_destroy(t_arc arc, t_drop destructor)
{
if (!arc)
return ;
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/04/29 16:08:57 by agilliar #+# #+# */
-/* Updated: 2026/04/30 17:48:05 by agilliar ### ########.fr */
+/* Updated: 2026/05/04 02:35:51 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
# include <stdint.h>
# include <stdbool.h>
-# if UINTPTR_MAX == 0xFFFFFFFFFFFFFFFF
+# if UINTPTR_MAX != 0xFFFFFFFFFFFFFFFF
+# error "Platform's pointers are not 64 bits"
+# endif
typedef uintptr_t t_usize;
typedef intptr_t t_isize;
-typedef uint8_t t_u8;
typedef union u_value t_value;
-typedef struct s_expr
-{
- t_usize fn;
- t_usize arg;
-} t_expr;
-
typedef t_value (*t_builtin)(t_value);
-typedef struct s_func
-{
- t_usize consts_cnt;
- t_value *consts;
- t_usize exprs_count;
- t_expr *exprs;
-} t_func;
-
enum e_value: t_usize
{
VALUE_PTR = 0,
VALUE_INT = 1,
};
-# define VALUE_MASK 0x1
+# define VALUE_MASK 0x1
typedef union u_value
{
enum e_value_ptr: t_usize
{
VALUE_PTR_BUILTIN,
- VALUE_PTR_FUNC,
VALUE_PTR_LIST,
VALUE_PTR_BYTES,
};
t_builtin builtin;
};
-struct s_value_func
-{
- enum e_value_ptr discrim;
- t_func func;
-};
-
struct s_value_list
{
t_usize len;
{
t_usize len;
enum e_value_ptr discrim;
- t_u8 bytes[0];
+ char bytes[0];
};
t_value value_builtin_new(t_builtin builtin);
-t_value value_func_new(t_func func);
t_value value_list_new(t_usize len);
t_value value_bytes_new(t_usize len);
+t_value value_undefined_new(void);
t_value value_int_new(t_isize n);
-t_builtin *value_builtin_get(t_value value);
-t_func *value_func_get(t_value value);
+struct s_value_builtin *value_builtin_get(t_value value);
struct s_value_list *value_list_get(t_value value);
struct s_value_bytes *value_bytes_get(t_value value);
t_isize value_int_get(t_value value);
-void t_value_destroy(t_value value);
-t_value t_value_copy(t_value value);
+void value_destroy(t_value value);
+
+t_value value_copy(t_value value);
+struct s_value_list *value_list_unique(t_value *value);
+struct s_value_bytes *value_bytes_unique(t_value *value);
+
+t_value value_list_new(t_usize len);
+t_value value_list_new(t_usize len);
typedef void *t_arc;
+typedef void *(*t_unpack)(t_value);
+typedef void (*t_drop)(void *);
t_arc arc_create(t_usize size);
t_arc arc_copy(t_arc arc);
void noop(void *ptr);
-# endif
+struct s_exec_context;
+
+typedef struct s_eval_ctx
+{
+ struct s_eval_ctx *parent;
+ struct s_value_list *state;
+ t_usize pos;
+} t_eval_ctx;
+
+// 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);
+
#endif
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* eval.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/05/04 01:21:34 by agilliar #+# #+# */
+/* Updated: 2026/05/04 02:51:20 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "ccera.h"
+#include <stdlib.h>
+
+static t_value ctx_eval(t_eval_ctx *ctx)
+{
+ (void) ctx;
+ return (value_undefined_new());
+}
+
+t_value expr_eval(t_value expr)
+{
+ t_eval_ctx *ctx;
+
+ (void) expr;
+ ctx = malloc(sizeof(t_eval_ctx));
+ if (!ctx)
+ return (value_undefined_new());
+ ctx->parent = NULL;
+ return (ctx_eval(ctx));
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* value_destroy.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/04/30 19:40:43 by agilliar #+# #+# */
+/* Updated: 2026/05/04 01:17:51 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "ccera.h"
+#include <stdlib.h>
+
+static void value_drop_arc(t_value *value, t_unpack unpack, t_drop drop)
+{
+ void *unpacked;
+
+ unpacked = unpack(*value);
+ if (!unpacked)
+ return ;
+ *value = value_int_new(0);
+ arc_destroy(unpacked, drop);
+}
+
+static void value_list_del(struct s_value_list *list)
+{
+ t_usize i;
+
+ i = 0;
+ while (i < list->len)
+ value_destroy(list->list[i++]);
+}
+
+void value_destroy(t_value value)
+{
+ value_drop_arc(&value, (t_unpack) value_builtin_get, noop);
+ value_drop_arc(&value, (t_unpack) value_list_get, (t_drop) value_list_del);
+ value_drop_arc(&value, (t_unpack) value_bytes_get, noop);
+}
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/04/30 17:27:40 by agilliar #+# #+# */
-/* Updated: 2026/04/30 17:48:45 by agilliar ### ########.fr */
+/* Updated: 2026/05/04 01:18:03 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
#include "ccera.h"
#include <stddef.h>
-t_builtin *value_builtin_get(t_value value)
+struct s_value_builtin *value_builtin_get(t_value value)
{
struct s_value_builtin *res;
res = value.ptr - offsetof(struct s_value_builtin, builtin);
if (res->discrim != VALUE_PTR_BUILTIN)
return (NULL);
- return (&res->builtin);
-}
-
-t_func *value_func_get(t_value value)
-{
- struct s_value_func *res;
-
- if ((value.discrim & VALUE_MASK) != VALUE_PTR)
- return (NULL);
- res = value.ptr - offsetof(struct s_value_func, func);
- if (res->discrim != VALUE_PTR_FUNC)
- return (NULL);
- return (&res->func);
+ return (res);
}
struct s_value_list *value_list_get(t_value value)
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* value_lifetime.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2026/05/04 02:05:48 by agilliar #+# #+# */
+/* Updated: 2026/05/04 03:21:18 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "ccera.h"
+#include <stddef.h>
+#include <string.h>
+
+t_value value_copy(t_value value)
+{
+ void *ptr;
+
+ ptr = value_list_get(value);
+ if (ptr)
+ {
+ arc_copy(ptr);
+ return (value);
+ }
+ ptr = value_bytes_get(value);
+ if (ptr)
+ {
+ arc_copy(ptr);
+ return (value);
+ }
+ ptr = value_builtin_get(value);
+ if (ptr)
+ {
+ arc_copy(ptr);
+ return (value);
+ }
+ return (value_int_new(value_int_get(value)));
+}
+
+struct s_value_list *value_list_unique(t_value *value)
+{
+ struct s_value_list *list;
+ t_value new;
+ struct s_value_list *new_list;
+ t_usize i;
+
+ list = value_list_get(*value);
+ if (!list)
+ return (NULL);
+ if (arc_is_unique(list))
+ return (list);
+ new = value_list_new(list->len);
+ new_list = value_list_get(new);
+ if (!new_list)
+ return (NULL);
+ i = 0;
+ while (i < list->len)
+ {
+ new_list->list[i] = value_copy(list->list[i]);
+ i++;
+ }
+ value_destroy(*value);
+ *value = new;
+ return (new_list);
+}
+
+struct s_value_bytes *value_bytes_unique(t_value *value)
+{
+ struct s_value_bytes *bytes;
+ t_value new;
+ struct s_value_bytes *new_bytes;
+
+ bytes = value_bytes_get(*value);
+ if (!bytes)
+ return (NULL);
+ if (arc_is_unique(bytes))
+ return (bytes);
+ new = value_bytes_new(bytes->len);
+ new_bytes = value_bytes_get(new);
+ if (!new_bytes)
+ return (NULL);
+ memcpy(new_bytes->bytes, bytes->bytes, bytes->len);
+ value_destroy(*value);
+ *value = new;
+ return (new_bytes);
+}
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/04/30 16:25:42 by agilliar #+# #+# */
-/* Updated: 2026/04/30 17:48:17 by agilliar ### ########.fr */
+/* Updated: 2026/05/04 01:49:28 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
res = arc_create(sizeof(struct s_value_builtin));
if (!res)
- return (value_int_new(0));
+ return (value_undefined_new());
res->discrim = VALUE_PTR_BUILTIN;
res->builtin = builtin;
res_raw.ptr = &res->builtin;
return (res_raw);
}
-t_value value_func_new(t_func func)
-{
- struct s_value_func *res;
- t_value res_raw;
-
- res = arc_create(sizeof(struct s_value_func));
- if (!res)
- return (value_int_new(0));
- res->discrim = VALUE_PTR_FUNC;
- res->func = func;
- res_raw.ptr = &res->func;
- res_raw.discrim |= VALUE_PTR;
- return (res_raw);
-}
-
t_value value_list_new(t_usize len)
{
struct s_value_list *res;
if (__builtin_mul_overflow(len, sizeof(t_value), &n)
|| __builtin_add_overflow(n, sizeof(struct s_value_list), &n))
- return (value_int_new(0));
+ return (value_undefined_new());
res = arc_create(n);
if (!res)
- return (value_int_new(0));
+ return (value_undefined_new());
res->discrim = VALUE_PTR_LIST;
res->len = len;
n = 0;
while (n < len)
- res->list[n++] = value_int_new(0);
+ res->list[n++] = value_undefined_new();
res_raw.ptr = &res->list;
res_raw.discrim |= VALUE_PTR;
return (res_raw);
t_usize n;
if (__builtin_add_overflow(len, sizeof(struct s_value_bytes), &n))
- return (value_int_new(0));
+ return (value_undefined_new());
res = arc_create(n);
if (!res)
- return (value_int_new(0));
+ return (value_undefined_new());
res->discrim = VALUE_PTR_BYTES;
res->len = len;
memset(&res->bytes, 0, len);
return (res_raw);
}
+t_value value_undefined_new(void)
+{
+ t_value res;
+
+ res.ptr = NULL;
+ return (res);
+}
+
t_value value_int_new(t_isize n)
{
t_value res;
/* By: agilliar <agilliar@student.42mulhouse.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/04/30 17:19:58 by agilliar #+# #+# */
-/* Updated: 2026/04/30 17:53:30 by agilliar ### ########.fr */
+/* Updated: 2026/05/04 03:20:35 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
char *s = "Hello cera!";
t_value value = value_bytes_new(strlen(s) + 1);
strcpy(&value_bytes_get(value)->bytes[0], s);
- printf("%s\n", &value_bytes_get(value)->bytes);
+ printf("%s\n", &value_bytes_get(value)->bytes[0]);
printf("%p\n", value_bytes_get(value));
printf("%p\n", value_list_get(value));
+ char c = value_bytes_get(value)->bytes[1];
+ (void) c;
+ t_value value_2 = value_copy(value);
+ value_bytes_unique(&value_2)->bytes[1] = 'f';
+ printf("%s\n", &value_bytes_get(value_2)->bytes[0]);
+ printf("%s\n", &value_bytes_get(value)->bytes[0]);
+ value_destroy(value);
+ value_destroy(value_2);
value = value_int_new(128);
printf("%li\n", value_int_get(value));
}