aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAryadev Chavali <aryadev@aryadevchavali.com>2025-08-19 23:20:19 +0100
committerAryadev Chavali <aryadev@aryadevchavali.com>2025-08-19 23:21:41 +0100
commit779c4b83055756a574f58e4097849a8acd6d5a32 (patch)
tree51f27b3ec9970b9a3cf33c46b10aab8d4308232d
parent7ac2a80b1143fac9190bbe62811ecc32403bfb98 (diff)
downloadalisp-779c4b83055756a574f58e4097849a8acd6d5a32.tar.gz
alisp-779c4b83055756a574f58e4097849a8acd6d5a32.tar.bz2
alisp-779c4b83055756a574f58e4097849a8acd6d5a32.zip
Conses and Vectors for my tagging scheme
Unfortunately, due to how vectors are implemented, pointers to them are unstable. We need to box them one more time (therefore adding a level of indirection) in order to stabilise them. This is annoying but currently necessary. Even if we implemented vectors as {u64, u64, ptr} instead of {u64, u64, bytes...}, we'd still have the same problem at access - two levels of indirection. I guess size and capacity checks would be one level of indirection which is nice at least, but we're already screwed at the point of doing lookup either way.
-rw-r--r--base.h39
-rw-r--r--tag.c22
2 files changed, 54 insertions, 7 deletions
diff --git a/base.h b/base.h
index ae62268..82d6b7f 100644
--- a/base.h
+++ b/base.h
@@ -81,28 +81,48 @@ void sym_table_init(sym_table_t *table);
char *sym_table_find(sym_table_t *table, sv_t sv);
void sym_table_cleanup(sym_table_t *table);
-/// Pointer tagging scheme for lisps
+/// Basic defintions for a Lisp
#define NIL 0
+
typedef struct Obj lisp_t;
+typedef struct
+{
+ lisp_t *car, *cdr;
+} cons_t;
+
+typedef struct
+{
+ // 2 levels of indirection... disgusting
+ void *data;
+} lvec_t;
+
+/// Pointer tagging scheme for lisps
+
typedef enum Tag
{
- TAG_NIL = 0b00000000,
+ TAG_NIL = 0b00000000, // Start of atomic types
TAG_INT = 0b00000001, // special so we can encode 63 bit integers
TAG_SYM = 0b00000100,
- NUM_TAGS = 3,
+ TAG_CONS = 0b00000010, // Start of container types
+ TAG_VEC = 0b00000110,
+ NUM_TAGS = 5,
} tag_t;
enum Shift
{
- SHIFT_INT = 1,
- SHIFT_SYM = 8,
+ SHIFT_INT = 1,
+ SHIFT_SYM = 8,
+ SHIFT_CONS = 8,
+ SHIFT_VEC = 8,
};
enum Mask
{
- MASK_INT = 0b00000001,
- MASK_SYM = 0b11111111,
+ MASK_INT = 0b00000001,
+ MASK_SYM = 0b11111111,
+ MASK_CONS = 0b11111111,
+ MASK_VEC = 0b11111111,
};
#define TAG(PTR, TYPE) ((lisp_t *)(((PTR) << SHIFT_##TYPE) | TAG_##TYPE))
@@ -114,7 +134,12 @@ enum Mask
lisp_t *tag_int(i64 i);
lisp_t *tag_sym(char *str);
+lisp_t *tag_cons(cons_t *cons);
+lisp_t *tag_vec(lvec_t *lvec);
+
i64 as_int(lisp_t *);
char *as_sym(lisp_t *);
+cons_t *as_cons(lisp_t *);
+void *as_vec(lisp_t *);
#endif
diff --git a/tag.c b/tag.c
index 7688d63..dbc47ba 100644
--- a/tag.c
+++ b/tag.c
@@ -13,6 +13,7 @@
*/
#include <assert.h>
+#include <stdlib.h>
#include "./base.h"
@@ -26,6 +27,11 @@ lisp_t *tag_sym(char *str)
return TAG((u64)str, SYM);
}
+lisp_t *tag_cons(cons_t *cons)
+{
+ return TAG((u64)cons, CONS);
+}
+
i64 as_int(lisp_t *obj)
{
assert(IS_TAG(obj, INT));
@@ -40,3 +46,19 @@ char *as_sym(lisp_t *obj)
assert(IS_TAG(obj, SYM));
return (char *)UNTAG(obj, SYM);
}
+
+cons_t *as_cons(lisp_t *obj)
+{
+ assert(IS_TAG(obj, CONS));
+ return (cons_t *)UNTAG(obj, CONS);
+}
+
+void *as_vec(lisp_t *obj)
+{
+ assert(IS_TAG(obj, VEC));
+ lvec_t *vec = (lvec_t *)UNTAG(obj, VEC);
+ if (vec)
+ return vec->data;
+ else
+ return NULL;
+}