]> Untitled Git - axy/ft/c-cera.git/commitdiff
Value and arcs!
authorAxy <gilliardmarthey.axel@gmail.com>
Thu, 30 Apr 2026 15:54:08 +0000 (17:54 +0200)
committerAxy <gilliardmarthey.axel@gmail.com>
Thu, 30 Apr 2026 15:54:08 +0000 (17:54 +0200)
.editorconfig [new file with mode: 0644]
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
a.out [new file with mode: 0755]
src/arc.c [new file with mode: 0644]
src/ccera.h [new file with mode: 0644]
src/value_get.c [new file with mode: 0644]
src/value_new.c [new file with mode: 0644]
test.c [new file with mode: 0644]

diff --git a/.editorconfig b/.editorconfig
new file mode 100644 (file)
index 0000000..0b225af
--- /dev/null
@@ -0,0 +1,2 @@
+[*]
+indent_style = tab
diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..c181c9d
--- /dev/null
@@ -0,0 +1,3 @@
+.build
+*.a
+.norm
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (executable)
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 (file)
index 0000000..bc811e1
--- /dev/null
+++ b/src/arc.c
@@ -0,0 +1,59 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   arc.c                                              :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   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       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "ccera.h"
+#include <stdlib.h>
+
+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 (file)
index 0000000..8c8a077
--- /dev/null
@@ -0,0 +1,117 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   ccera.h                                            :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   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       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#ifndef CCERA_H
+# define CCERA_H
+
+# include <stdint.h>
+# include <stdbool.h>
+
+# 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 (file)
index 0000000..6f76a46
--- /dev/null
@@ -0,0 +1,67 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   value_get.c                                        :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   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       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "ccera.h"
+#include <stddef.h>
+
+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 (file)
index 0000000..b461a2c
--- /dev/null
@@ -0,0 +1,94 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   value_new.c                                        :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   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       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "ccera.h"
+#include <string.h>
+
+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 (file)
index 0000000..162a8e6
--- /dev/null
+++ b/test.c
@@ -0,0 +1,27 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   test.c                                             :+:      :+:    :+:   */
+/*                                                    +:+ +:+         +:+     */
+/*   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       */
+/*                                                                            */
+/* ************************************************************************** */
+
+#include "src/ccera.h"
+#include <string.h>
+#include <stdio.h>
+
+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));
+}