diff options
| author | Aryadev Chavali <aryadev@aryadevchavali.com> | 2025-08-19 23:20:19 +0100 | 
|---|---|---|
| committer | Aryadev Chavali <aryadev@aryadevchavali.com> | 2025-08-19 23:21:41 +0100 | 
| commit | 779c4b83055756a574f58e4097849a8acd6d5a32 (patch) | |
| tree | 51f27b3ec9970b9a3cf33c46b10aab8d4308232d | |
| parent | 7ac2a80b1143fac9190bbe62811ecc32403bfb98 (diff) | |
| download | alisp-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.h | 39 | ||||
| -rw-r--r-- | tag.c | 22 | 
2 files changed, 54 insertions, 7 deletions
@@ -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 @@ -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; +}  | 
