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.
This commit is contained in:
39
base.h
39
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);
|
char *sym_table_find(sym_table_t *table, sv_t sv);
|
||||||
void sym_table_cleanup(sym_table_t *table);
|
void sym_table_cleanup(sym_table_t *table);
|
||||||
|
|
||||||
/// Pointer tagging scheme for lisps
|
/// Basic defintions for a Lisp
|
||||||
#define NIL 0
|
#define NIL 0
|
||||||
|
|
||||||
typedef struct Obj lisp_t;
|
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
|
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_INT = 0b00000001, // special so we can encode 63 bit integers
|
||||||
TAG_SYM = 0b00000100,
|
TAG_SYM = 0b00000100,
|
||||||
NUM_TAGS = 3,
|
TAG_CONS = 0b00000010, // Start of container types
|
||||||
|
TAG_VEC = 0b00000110,
|
||||||
|
NUM_TAGS = 5,
|
||||||
} tag_t;
|
} tag_t;
|
||||||
|
|
||||||
enum Shift
|
enum Shift
|
||||||
{
|
{
|
||||||
SHIFT_INT = 1,
|
SHIFT_INT = 1,
|
||||||
SHIFT_SYM = 8,
|
SHIFT_SYM = 8,
|
||||||
|
SHIFT_CONS = 8,
|
||||||
|
SHIFT_VEC = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Mask
|
enum Mask
|
||||||
{
|
{
|
||||||
MASK_INT = 0b00000001,
|
MASK_INT = 0b00000001,
|
||||||
MASK_SYM = 0b11111111,
|
MASK_SYM = 0b11111111,
|
||||||
|
MASK_CONS = 0b11111111,
|
||||||
|
MASK_VEC = 0b11111111,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TAG(PTR, TYPE) ((lisp_t *)(((PTR) << SHIFT_##TYPE) | TAG_##TYPE))
|
#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_int(i64 i);
|
||||||
lisp_t *tag_sym(char *str);
|
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 *);
|
i64 as_int(lisp_t *);
|
||||||
char *as_sym(lisp_t *);
|
char *as_sym(lisp_t *);
|
||||||
|
cons_t *as_cons(lisp_t *);
|
||||||
|
void *as_vec(lisp_t *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
22
tag.c
22
tag.c
@@ -13,6 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "./base.h"
|
#include "./base.h"
|
||||||
|
|
||||||
@@ -26,6 +27,11 @@ lisp_t *tag_sym(char *str)
|
|||||||
return TAG((u64)str, SYM);
|
return TAG((u64)str, SYM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lisp_t *tag_cons(cons_t *cons)
|
||||||
|
{
|
||||||
|
return TAG((u64)cons, CONS);
|
||||||
|
}
|
||||||
|
|
||||||
i64 as_int(lisp_t *obj)
|
i64 as_int(lisp_t *obj)
|
||||||
{
|
{
|
||||||
assert(IS_TAG(obj, INT));
|
assert(IS_TAG(obj, INT));
|
||||||
@@ -40,3 +46,19 @@ char *as_sym(lisp_t *obj)
|
|||||||
assert(IS_TAG(obj, SYM));
|
assert(IS_TAG(obj, SYM));
|
||||||
return (char *)UNTAG(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;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user