diff options
-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; +} |