From: Axy Date: Thu, 30 Apr 2026 15:54:08 +0000 (+0200) Subject: Value and arcs! X-Git-Url: https://git.uwuaxy.net/?a=commitdiff_plain;h=c7a4e8c40015cb3e4844314d0f61913513038ad5;p=axy%2Fft%2Fc-cera.git Value and arcs! --- c7a4e8c40015cb3e4844314d0f61913513038ad5 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..0b225af --- /dev/null +++ b/.editorconfig @@ -0,0 +1,2 @@ +[*] +indent_style = tab diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c181c9d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.build +*.a +.norm diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2ab5fa8 --- /dev/null +++ b/Makefile @@ -0,0 +1,57 @@ +NAME=ccera.a + +SRCS=src/arc.c src/value_get.c src/value_new.c + +HEADERS=src/ccera.h + +BUILDDIR=.build + +THIS=Makefile + +OBJS=${SRCS:src/%.c=${BUILDDIR}/%.o} + +CFLAGS=-Wall -Wextra -Werror -g -pthread -O3 + +CC=cc + +MAKEFLAGS += --no-print-directory + +all : ${NAME} + +${BUILDDIR}/%.o : src/%.c ${HEADERS} | ${BUILDDIR} + ${CC} ${CFLAGS} -c -o $@ $< + +${BUILDDIR} : + mkdir ${BUILDDIR} + +${NAME} : ${OBJS} + ar rcs $@ $^ + +clean : + rm -f ${OBJS} + +fclean : clean + rm -f ${NAME} + rm -fd ${BUILDDIR} + +re : fclean all + +remakefile : clean + sed -i "s?^SRCS=.*?$$(echo -n SRCS=; echo -n src/*.c)?" ${THIS} + sed -i "s?^HEADERS=.*?$$(echo -n HEADERS=; echo -n src/*.h)?" ${THIS} + +.norm: ${SRCS} ${HEADERS} ${THIS} + @rm -f .norm_fail + @norminette ${SRCS} ${HEADERS} > .norm || touch .norm_fail + +norm: .norm + @cat .norm + @test ! -e .norm_fail + +norm-watch: + watch -c -n 1 make norm + +build-watch: + watch -c -n 1 make + +.PHONY : all clean fclean re remakefile norm norm-watch build-watch diff --git a/a.out b/a.out new file mode 100755 index 0000000..96b9661 Binary files /dev/null and b/a.out differ diff --git a/src/arc.c b/src/arc.c new file mode 100644 index 0000000..bc811e1 --- /dev/null +++ b/src/arc.c @@ -0,0 +1,59 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* arc.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/29 16:40:27 by agilliar #+# #+# */ +/* Updated: 2026/04/30 15:04:33 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ccera.h" +#include + +t_arc arc_create(t_usize size) +{ + t_usize *res; + + if (__builtin_add_overflow(size, sizeof(t_usize), &size)) + return (NULL); + res = malloc(size); + if (!res) + return (NULL); + res[0] = 1; + return ((void *) &res[1]); +} + +t_arc arc_copy(t_arc arc) +{ + if (!arc) + return (NULL); + if (__atomic_add_fetch(((t_usize *)arc) - 1, 1, __ATOMIC_RELAXED) + < ((t_usize) 1) << (sizeof(t_usize) * 8 - 1)) + return (arc); + arc_destroy(arc, noop); + return (NULL); +} + +void arc_destroy(t_arc arc, void (*destructor)(void *)) +{ + if (!arc) + return ; + if (__atomic_sub_fetch(((t_usize *)arc) - 1, 1, __ATOMIC_RELEASE) != 0) + return ; + __atomic_thread_fence(__ATOMIC_ACQUIRE); + destructor(arc); + free(arc - 8); +} + +bool arc_is_unique(t_arc arc) +{ + return (__atomic_load_n(((t_usize *)arc) - 1, __ATOMIC_ACQUIRE) == 1); +} + +void noop(void *ptr) +{ + (void) ptr; +} diff --git a/src/ccera.h b/src/ccera.h new file mode 100644 index 0000000..8c8a077 --- /dev/null +++ b/src/ccera.h @@ -0,0 +1,117 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ccera.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/29 16:08:57 by agilliar #+# #+# */ +/* Updated: 2026/04/30 17:48:05 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef CCERA_H +# define CCERA_H + +# include +# include + +# if UINTPTR_MAX == 0xFFFFFFFFFFFFFFFF + +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 + +typedef union u_value +{ + void *ptr; + t_isize integral; + enum e_value discrim; +} t_value; + +enum e_value_ptr: t_usize +{ + VALUE_PTR_BUILTIN, + VALUE_PTR_FUNC, + VALUE_PTR_LIST, + VALUE_PTR_BYTES, +}; + +struct s_value_builtin +{ + enum e_value_ptr discrim; + t_builtin builtin; +}; + +struct s_value_func +{ + enum e_value_ptr discrim; + t_func func; +}; + +struct s_value_list +{ + t_usize len; + enum e_value_ptr discrim; + t_value list[0]; +}; + +struct s_value_bytes +{ + t_usize len; + enum e_value_ptr discrim; + t_u8 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_int_new(t_isize n); + +t_builtin *value_builtin_get(t_value value); +t_func *value_func_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); + +typedef void *t_arc; + +t_arc arc_create(t_usize size); +t_arc arc_copy(t_arc arc); +void arc_destroy(t_arc arc, void (*destructor)(void *)); +bool arc_is_unique(t_arc arc); + +void noop(void *ptr); + +# endif +#endif diff --git a/src/value_get.c b/src/value_get.c new file mode 100644 index 0000000..6f76a46 --- /dev/null +++ b/src/value_get.c @@ -0,0 +1,67 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* value_get.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/30 17:27:40 by agilliar #+# #+# */ +/* Updated: 2026/04/30 17:48:45 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ccera.h" +#include + +t_builtin *value_builtin_get(t_value value) +{ + struct s_value_builtin *res; + + if ((value.discrim & VALUE_MASK) != VALUE_PTR) + return (NULL); + 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); +} + +struct s_value_list *value_list_get(t_value value) +{ + struct s_value_list *res; + + if ((value.discrim & VALUE_MASK) != VALUE_PTR) + return (NULL); + res = value.ptr - offsetof(struct s_value_list, list); + if (res->discrim != VALUE_PTR_LIST) + return (NULL); + return (res); +} + +struct s_value_bytes *value_bytes_get(t_value value) +{ + struct s_value_bytes *res; + + if ((value.discrim & VALUE_MASK) != VALUE_PTR) + return (NULL); + res = value.ptr - offsetof(struct s_value_bytes, bytes); + if (res->discrim != VALUE_PTR_BYTES) + return (NULL); + return (res); +} + +t_isize value_int_get(t_value value) +{ + return (value.integral >> 1); +} diff --git a/src/value_new.c b/src/value_new.c new file mode 100644 index 0000000..b461a2c --- /dev/null +++ b/src/value_new.c @@ -0,0 +1,94 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* value_new.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/30 16:25:42 by agilliar #+# #+# */ +/* Updated: 2026/04/30 17:48:17 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ccera.h" +#include + +t_value value_builtin_new(t_builtin builtin) +{ + struct s_value_builtin *res; + t_value res_raw; + + res = arc_create(sizeof(struct s_value_builtin)); + if (!res) + return (value_int_new(0)); + res->discrim = VALUE_PTR_BUILTIN; + res->builtin = builtin; + res_raw.ptr = &res->builtin; + res_raw.discrim |= VALUE_PTR; + 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; + t_value res_raw; + t_usize n; + + if (__builtin_mul_overflow(len, sizeof(t_value), &n) + || __builtin_add_overflow(n, sizeof(struct s_value_list), &n)) + return (value_int_new(0)); + res = arc_create(n); + if (!res) + return (value_int_new(0)); + res->discrim = VALUE_PTR_LIST; + res->len = len; + n = 0; + while (n < len) + res->list[n++] = value_int_new(0); + res_raw.ptr = &res->list; + res_raw.discrim |= VALUE_PTR; + return (res_raw); +} + +t_value value_bytes_new(t_usize len) +{ + struct s_value_bytes *res; + t_value res_raw; + t_usize n; + + if (__builtin_add_overflow(len, sizeof(struct s_value_bytes), &n)) + return (value_int_new(0)); + res = arc_create(n); + if (!res) + return (value_int_new(0)); + res->discrim = VALUE_PTR_BYTES; + res->len = len; + memset(&res->bytes, 0, len); + res_raw.ptr = &res->bytes; + res_raw.discrim |= VALUE_PTR; + return (res_raw); +} + +t_value value_int_new(t_isize n) +{ + t_value res; + + res.integral = n << 1; + res.discrim |= VALUE_INT; + return (res); +} diff --git a/test.c b/test.c new file mode 100644 index 0000000..162a8e6 --- /dev/null +++ b/test.c @@ -0,0 +1,27 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* test.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agilliar +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2026/04/30 17:19:58 by agilliar #+# #+# */ +/* Updated: 2026/04/30 17:53:30 by agilliar ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "src/ccera.h" +#include +#include + +int main(void) +{ + 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("%p\n", value_bytes_get(value)); + printf("%p\n", value_list_get(value)); + value = value_int_new(128); + printf("%li\n", value_int_get(value)); +}