mirror of
https://github.com/janet-lang/janet
synced 2024-11-28 02:59:54 +00:00
More work on nanbox implementation.
This commit is contained in:
parent
b568a6bc88
commit
eceb6e5a77
3
.gitignore
vendored
3
.gitignore
vendored
@ -11,6 +11,9 @@ dst
|
||||
# Tools
|
||||
xxd
|
||||
|
||||
# Swap files
|
||||
*.swp
|
||||
|
||||
# Tags
|
||||
tags
|
||||
|
||||
|
3
Makefile
3
Makefile
@ -79,7 +79,7 @@ CCU_FLAGS = $(CFLAGS) -DDST_UNIT_TEST
|
||||
|
||||
DST_UNIT_BINARIES=$(addprefix unittests/,\
|
||||
asm_test.out array_test.out buffer_test.out fiber_test.out \
|
||||
nanbox_test.out parse_test.out table_test.out)
|
||||
parse_test.out table_test.out)
|
||||
|
||||
%.out: %.c $(DST_CORE_OBJECTS) $(DST_ALL_HEADERS) unittests/unit.h
|
||||
$(CC) $(CCU_FLAGS) $(DST_CORE_OBJECTS) $< -o $@
|
||||
@ -89,7 +89,6 @@ unit: $(DST_UNIT_BINARIES)
|
||||
unittests/asm_test.out
|
||||
unittests/buffer_test.out
|
||||
unittests/fiber_test.out
|
||||
unittests/nanbox_test.out
|
||||
unittests/parse_test.out
|
||||
unittests/table_test.out
|
||||
|
||||
|
@ -60,12 +60,13 @@ void dst_array_ensure(DstArray *array, int32_t capacity) {
|
||||
|
||||
/* Set the count of an array. Extend with nil if needed. */
|
||||
void dst_array_setcount(DstArray *array, int32_t count) {
|
||||
if (count < 0)
|
||||
return;
|
||||
if (count > array->count) {
|
||||
dst_array_ensure(array, count + 1);
|
||||
dst_memempty(array->data + array->count, count - array->count);
|
||||
}
|
||||
if (count > 0)
|
||||
array->count = count;
|
||||
array->count = count;
|
||||
}
|
||||
|
||||
/* Push a value to the top of the array */
|
||||
|
@ -172,7 +172,7 @@ static void dst_mark_funcdef(DstFuncDef *def) {
|
||||
for (i = 0; i < count; ++i) {
|
||||
DstValue v = def->constants[i];
|
||||
/* Funcdefs use nil literals to store other funcdefs */
|
||||
if (v.type == DST_NIL) {
|
||||
if (dst_checktype(v, DST_NIL)) {
|
||||
dst_mark_funcdef((DstFuncDef *) dst_unwrap_pointer(v));
|
||||
} else {
|
||||
dst_mark(v);
|
||||
|
117
core/string.c
117
core/string.c
@ -319,13 +319,14 @@ void dst_short_description_b(DstBuffer *buffer, DstValue x) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper structure for stringifying deeply nested structures */
|
||||
/* Helper structure for stringifying nested structures */
|
||||
typedef struct DstPrinter DstPrinter;
|
||||
struct DstPrinter {
|
||||
DstBuffer buffer;
|
||||
DstTable seen;
|
||||
uint32_t flags;
|
||||
int64_t next;
|
||||
uint32_t state;
|
||||
int32_t next;
|
||||
int32_t indent;
|
||||
int32_t indent_size;
|
||||
int32_t token_line_limit;
|
||||
@ -399,7 +400,7 @@ static void dst_print_hashtable_inner(DstPrinter *p, const DstValue *data, int32
|
||||
dst_buffer_push_u8(&p->buffer, '\n');
|
||||
p->indent++;
|
||||
for (i = 0; i < cap; i += 2) {
|
||||
if (dst_checktype(data[i], DST_NIL)) {
|
||||
if (!dst_checktype(data[i], DST_NIL)) {
|
||||
dst_print_indent(p);
|
||||
dst_description_helper(p, data[i]);
|
||||
dst_buffer_push_u8(&p->buffer, ' ');
|
||||
@ -412,7 +413,7 @@ static void dst_print_hashtable_inner(DstPrinter *p, const DstValue *data, int32
|
||||
} else {
|
||||
int isfirst = 1;
|
||||
for (i = 0; i < cap; i += 2) {
|
||||
if (dst_checktype(data[i], DST_NIL)) {
|
||||
if (!dst_checktype(data[i], DST_NIL)) {
|
||||
if (isfirst)
|
||||
isfirst = 0;
|
||||
else
|
||||
@ -462,52 +463,57 @@ static void dst_print_seq_inner(DstPrinter *p, const DstValue *data, int32_t len
|
||||
|
||||
/* Static debug print helper */
|
||||
static void dst_description_helper(DstPrinter *p, DstValue x) {
|
||||
const char *open;
|
||||
const char *close;
|
||||
int32_t len, cap;
|
||||
const DstValue *data;
|
||||
DstValue check;
|
||||
p->depth--;
|
||||
DstValue check = dst_table_get(&p->seen, x);
|
||||
switch (dst_type(x)) {
|
||||
default:
|
||||
if (p->flags & DST_PRINTFLAG_COLORIZE) {
|
||||
dst_buffer_push_cstring(&p->buffer, dst_type_colors[dst_type(x)]);
|
||||
dst_short_description_b(&p->buffer, x);
|
||||
dst_buffer_push_cstring(&p->buffer, "\x1B[0m");
|
||||
} else {
|
||||
dst_short_description_b(&p->buffer, x);
|
||||
}
|
||||
p->depth++;
|
||||
return;
|
||||
case DST_STRUCT:
|
||||
open = "{"; close = "}";
|
||||
break;
|
||||
case DST_TABLE:
|
||||
open = "@{"; close = "}";
|
||||
break;
|
||||
case DST_TUPLE:
|
||||
open = "("; close = ")";
|
||||
break;
|
||||
case DST_ARRAY:
|
||||
open = "["; close = "]";
|
||||
break;
|
||||
}
|
||||
if (!p->state) {
|
||||
dst_table_init(&p->seen, 10);
|
||||
p->state = 1;
|
||||
}
|
||||
check = dst_table_get(&p->seen, x);
|
||||
if (dst_checktype(check, DST_INTEGER)) {
|
||||
dst_buffer_push_cstring(&p->buffer, "<cycle ");
|
||||
integer_to_string_b(&p->buffer, dst_unwrap_integer(check));
|
||||
dst_buffer_push_cstring(&p->buffer, ">");
|
||||
} else {
|
||||
const char *open;
|
||||
const char *close;
|
||||
int32_t len, cap;
|
||||
const DstValue *data;
|
||||
switch (dst_type(x)) {
|
||||
default:
|
||||
if (p->flags & DST_PRINTFLAG_COLORIZE) {
|
||||
dst_buffer_push_cstring(&p->buffer, dst_type_colors[dst_type(x)]);
|
||||
dst_short_description_b(&p->buffer, x);
|
||||
dst_buffer_push_cstring(&p->buffer, "\x1B[0m");
|
||||
} else {
|
||||
dst_short_description_b(&p->buffer, x);
|
||||
}
|
||||
p->depth++;
|
||||
return;
|
||||
case DST_STRUCT:
|
||||
open = "{"; close = "}";
|
||||
break;
|
||||
case DST_TABLE:
|
||||
open = "@{"; close = "}";
|
||||
break;
|
||||
case DST_TUPLE:
|
||||
open = "("; close = ")";
|
||||
break;
|
||||
case DST_ARRAY:
|
||||
open = "["; close = "]";
|
||||
break;
|
||||
}
|
||||
dst_table_put(&p->seen, x, dst_wrap_integer(p->next++));
|
||||
dst_buffer_push_cstring(&p->buffer, open);
|
||||
if (p->depth == 0) {
|
||||
dst_buffer_push_cstring(&p->buffer, "...");
|
||||
} else if (dst_hashtable_view(x, &data, &len, &cap)) {
|
||||
dst_print_hashtable_inner(p, data, len, cap);
|
||||
} else if (dst_seq_view(x, &data, &len)) {
|
||||
dst_print_seq_inner(p, data, len);
|
||||
}
|
||||
dst_buffer_push_cstring(&p->buffer, close);
|
||||
return;
|
||||
}
|
||||
dst_table_put(&p->seen, x, dst_wrap_integer(p->next++));
|
||||
dst_buffer_push_cstring(&p->buffer, open);
|
||||
if (p->depth == 0) {
|
||||
dst_buffer_push_cstring(&p->buffer, "...");
|
||||
} else if (dst_hashtable_view(x, &data, &len, &cap)) {
|
||||
dst_print_hashtable_inner(p, data, len, cap);
|
||||
} else if (dst_seq_view(x, &data, &len)) {
|
||||
dst_print_seq_inner(p, data, len);
|
||||
}
|
||||
dst_buffer_push_cstring(&p->buffer, close);
|
||||
/* Remove from seen as we know that printing completes, we
|
||||
* can print in multiple times and we know we are not recursing */
|
||||
dst_table_remove(&p->seen, x);
|
||||
@ -530,16 +536,16 @@ const uint8_t *dst_description(DstValue x) {
|
||||
const uint8_t *ret;
|
||||
|
||||
dst_printer_defaults(&printer);
|
||||
printer.state = 0;
|
||||
dst_buffer_init(&printer.buffer, 0);
|
||||
dst_table_init(&printer.seen, 10);
|
||||
|
||||
/* Only print description up to a depth of 4 */
|
||||
dst_description_helper(&printer, x);
|
||||
ret = dst_string(printer.buffer.data, printer.buffer.count);
|
||||
|
||||
dst_buffer_deinit(&printer.buffer);
|
||||
dst_table_deinit(&printer.seen);
|
||||
|
||||
if (printer.state)
|
||||
dst_table_deinit(&printer.seen);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -564,6 +570,7 @@ const uint8_t *dst_formatc(const char *format, ...) {
|
||||
const uint8_t *ret;
|
||||
DstPrinter printer;
|
||||
DstBuffer *bufp = &printer.buffer;
|
||||
printer.state = 0;
|
||||
|
||||
/* Calculate length */
|
||||
while (format[len]) len++;
|
||||
@ -607,13 +614,10 @@ const uint8_t *dst_formatc(const char *format, ...) {
|
||||
case 'c':
|
||||
dst_buffer_push_u8(bufp, va_arg(args, int64_t));
|
||||
break;
|
||||
case 'p':
|
||||
case 'v':
|
||||
{
|
||||
dst_printer_defaults(&printer);
|
||||
dst_table_init(&printer.seen, 10);
|
||||
/* Only print description up to a depth of 4 */
|
||||
dst_description_helper(&printer, va_arg(args, DstValue));
|
||||
dst_table_deinit(&printer.seen);
|
||||
break;
|
||||
}
|
||||
case 'q':
|
||||
@ -629,14 +633,7 @@ const uint8_t *dst_formatc(const char *format, ...) {
|
||||
}
|
||||
case 'V':
|
||||
{
|
||||
const uint8_t *str = dst_short_description(va_arg(args, DstValue));
|
||||
dst_buffer_push_bytes(bufp, str, dst_string_length(str));
|
||||
break;
|
||||
}
|
||||
case 'v':
|
||||
{
|
||||
const uint8_t *str = dst_description(va_arg(args, DstValue));
|
||||
dst_buffer_push_bytes(bufp, str, dst_string_length(str));
|
||||
dst_short_description_b(bufp, va_arg(args, DstValue));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -648,6 +645,8 @@ const uint8_t *dst_formatc(const char *format, ...) {
|
||||
|
||||
ret = dst_string(printer.buffer.data, printer.buffer.count);
|
||||
dst_buffer_deinit(&printer.buffer);
|
||||
if (printer.state)
|
||||
dst_table_deinit(&printer.seen);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
|
||||
#include <dst/dst.h>
|
||||
|
||||
#define dst_struct_maphash(cap, hash) (((uint32_t)(hash) % (cap)) & 0xFFFFFFFE);
|
||||
|
||||
/* Begin creation of a struct */
|
||||
DstValue *dst_struct_begin(int32_t count) {
|
||||
/* This expression determines size of structs. It must be a pure
|
||||
@ -30,10 +32,11 @@ DstValue *dst_struct_begin(int32_t count) {
|
||||
* sizeof(int32_t) * 2 + 2 * count * sizeof(DstValue). Adding more space
|
||||
* ensures that structs are less likely to have hash collisions. If more space
|
||||
* is added or s is changed, change the macro dst_struct_capacity in internal.h */
|
||||
size_t s = sizeof(int32_t) * 2 + 4 * count * sizeof(DstValue);
|
||||
int32_t capacity = 4 * count;
|
||||
size_t s = sizeof(int32_t) * 2 + (capacity * sizeof(DstValue));
|
||||
char *data = dst_alloc(DST_MEMORY_STRUCT, s);
|
||||
memset(data, 0, s);
|
||||
DstValue *st = (DstValue *) (data + 2 * sizeof(int32_t));
|
||||
dst_memempty(st, capacity);
|
||||
dst_struct_length(st) = count;
|
||||
/* Use the hash storage space as a counter to see how many items
|
||||
* were successfully added. If this number is not equal to the
|
||||
@ -46,13 +49,13 @@ DstValue *dst_struct_begin(int32_t count) {
|
||||
/* Find an item in a struct */
|
||||
static const DstValue *dst_struct_find(const DstValue *st, DstValue key) {
|
||||
int32_t cap = dst_struct_capacity(st);
|
||||
int32_t index = (dst_hash(key) % cap) & (~1);
|
||||
int32_t index = dst_struct_maphash(cap, dst_hash(key));
|
||||
int32_t i;
|
||||
for (i = index; i < cap; i += 2)
|
||||
if (st[i].type == DST_NIL || dst_equals(st[i], key))
|
||||
if (dst_checktype(st[i], DST_NIL) || dst_equals(st[i], key))
|
||||
return st + i;
|
||||
for (i = 0; i < index; i += 2)
|
||||
if (st[i].type == DST_NIL || dst_equals(st[i], key))
|
||||
if (dst_checktype(st[i], DST_NIL) || dst_equals(st[i], key))
|
||||
return st + i;
|
||||
return NULL;
|
||||
}
|
||||
@ -63,10 +66,10 @@ static const DstValue *dst_struct_find(const DstValue *st, DstValue key) {
|
||||
void dst_struct_put(DstValue *st, DstValue key, DstValue value) {
|
||||
int32_t cap = dst_struct_capacity(st);
|
||||
int32_t hash = dst_hash(key);
|
||||
int32_t index = (hash % cap) & (~1);
|
||||
int32_t index = dst_struct_maphash(cap, hash);
|
||||
int32_t i, j, dist;
|
||||
int32_t bounds[4] = {index, cap, 0, index};
|
||||
if (key.type == DST_NIL || value.type == DST_NIL) return;
|
||||
if (dst_checktype(key, DST_NIL) || dst_checktype(value, DST_NIL)) return;
|
||||
/* Avoid extra items */
|
||||
if (dst_struct_hash(st) == dst_struct_length(st)) return;
|
||||
for (dist = 0, j = 0; j < 4; j += 2)
|
||||
@ -75,7 +78,7 @@ void dst_struct_put(DstValue *st, DstValue key, DstValue value) {
|
||||
int32_t otherhash;
|
||||
int32_t otherindex, otherdist;
|
||||
/* We found an empty slot, so just add key and value */
|
||||
if (st[i].type == DST_NIL) {
|
||||
if (dst_checktype(st[i], DST_NIL)) {
|
||||
st[i] = key;
|
||||
st[i + 1] = value;
|
||||
/* Update the temporary count */
|
||||
@ -88,7 +91,7 @@ void dst_struct_put(DstValue *st, DstValue key, DstValue value) {
|
||||
* with different order have the same internal layout, and therefor
|
||||
* will compare properly - i.e., {1 2 3 4} should equal {3 4 1 2}. */
|
||||
otherhash = dst_hash(st[i]);
|
||||
otherindex = (otherhash % cap) & (~1);
|
||||
otherindex = dst_struct_maphash(cap, otherhash);
|
||||
otherdist = (i + cap - otherindex) % cap;
|
||||
if (dist < otherdist)
|
||||
status = -1;
|
||||
@ -131,27 +134,25 @@ const DstValue *dst_struct_end(DstValue *st) {
|
||||
DstValue *newst;
|
||||
realCount = 0;
|
||||
for (i = 0; i < dst_struct_capacity(st); i += 2) {
|
||||
realCount += st[i].type != DST_NIL;
|
||||
realCount += dst_checktype(st[i], DST_NIL) ? 1 : 0;
|
||||
}
|
||||
newst = dst_struct_begin(realCount);
|
||||
for (i = 0; i < dst_struct_capacity(st); i += 2) {
|
||||
if (st[i].type != DST_NIL) {
|
||||
if (!dst_checktype(st[i], DST_NIL)) {
|
||||
dst_struct_put(newst, st[i], st[i + 1]);
|
||||
}
|
||||
}
|
||||
st = newst;
|
||||
}
|
||||
dst_struct_hash(st) = 0;
|
||||
dst_struct_hash(st) = dst_array_calchash(st, dst_struct_capacity(st));
|
||||
return (const DstValue *)st;
|
||||
}
|
||||
|
||||
/* Get an item from a struct */
|
||||
DstValue dst_struct_get(const DstValue *st, DstValue key) {
|
||||
const DstValue *bucket = dst_struct_find(st, key);
|
||||
if (!bucket || bucket[0].type == DST_NIL) {
|
||||
DstValue ret;
|
||||
ret.type = DST_NIL;
|
||||
return ret;
|
||||
if (NULL == bucket || dst_checktype(*bucket, DST_NIL)) {
|
||||
return dst_wrap_nil();
|
||||
} else {
|
||||
return bucket[1];
|
||||
}
|
||||
@ -161,16 +162,16 @@ DstValue dst_struct_get(const DstValue *st, DstValue key) {
|
||||
DstValue dst_struct_next(const DstValue *st, DstValue key) {
|
||||
const DstValue *bucket, *end;
|
||||
end = st + dst_struct_capacity(st);
|
||||
if (key.type == DST_NIL) {
|
||||
if (dst_checktype(key, DST_NIL)) {
|
||||
bucket = st;
|
||||
} else {
|
||||
bucket = dst_struct_find(st, key);
|
||||
if (!bucket || bucket[0].type == DST_NIL)
|
||||
if (NULL == bucket || dst_checktype(*bucket, DST_NIL))
|
||||
return dst_wrap_nil();
|
||||
bucket += 2;
|
||||
}
|
||||
for (; bucket < end; bucket += 2) {
|
||||
if (bucket[0].type != DST_NIL)
|
||||
if (!dst_checktype(bucket[0], DST_NIL))
|
||||
return bucket[0];
|
||||
}
|
||||
return dst_wrap_nil();
|
||||
@ -181,7 +182,7 @@ DstTable *dst_struct_to_table(const DstValue *st) {
|
||||
DstTable *table = dst_table(dst_struct_capacity(st));
|
||||
int32_t i;
|
||||
for (i = 0; i < dst_struct_capacity(st); i += 2) {
|
||||
if (st[i].type != DST_NIL) {
|
||||
if (!dst_checktype(st[i], DST_NIL)) {
|
||||
dst_table_put(table, st[i], st[i + 1]);
|
||||
}
|
||||
}
|
||||
@ -235,3 +236,5 @@ int dst_struct_compare(const DstValue *lhs, const DstValue *rhs) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef dst_struct_maphash
|
||||
|
@ -64,13 +64,13 @@ static const uint8_t **dst_symcache_findmem(
|
||||
int32_t len,
|
||||
int32_t hash,
|
||||
int *success) {
|
||||
int32_t bounds[4];
|
||||
int32_t i, j, index;
|
||||
uint32_t bounds[4];
|
||||
uint32_t i, j, index;
|
||||
const uint8_t **firstEmpty = NULL;
|
||||
|
||||
/* We will search two ranges - index to the end,
|
||||
* and 0 to the index. */
|
||||
index = hash % dst_vm_cache_capacity;
|
||||
index = (uint32_t)hash % dst_vm_cache_capacity;
|
||||
bounds[0] = index;
|
||||
bounds[1] = dst_vm_cache_capacity;
|
||||
bounds[2] = 0;
|
||||
@ -110,8 +110,8 @@ static const uint8_t **dst_symcache_findmem(
|
||||
dst_symcache_findmem((str), dst_string_length(str), dst_string_hash(str), (success))
|
||||
|
||||
/* Resize the cache. */
|
||||
static void dst_cache_resize(int32_t newCapacity) {
|
||||
int32_t i, oldCapacity;
|
||||
static void dst_cache_resize(uint32_t newCapacity) {
|
||||
uint32_t i, oldCapacity;
|
||||
const uint8_t **oldCache = dst_vm_cache;
|
||||
const uint8_t **newCache = calloc(1, newCapacity * sizeof(const uint8_t **));
|
||||
if (newCache == NULL) {
|
||||
|
@ -109,7 +109,7 @@ int dst_sys_get(DstValue *argv, int32_t argn) {
|
||||
ds = argv[0];
|
||||
for (i = 1; i < argn; i++) {
|
||||
ds = dst_get(ds, argv[i]);
|
||||
if (ds.type == DST_NIL)
|
||||
if (dst_checktype(ds, DST_NIL))
|
||||
break;
|
||||
}
|
||||
dst_vm_fiber->ret = ds;
|
||||
|
10
core/table.c
10
core/table.c
@ -22,11 +22,13 @@
|
||||
|
||||
#include <dst/dst.h>
|
||||
|
||||
#define dst_table_maphash(cap, hash) (((uint32_t)(hash) % (cap)) & 0xFFFFFFFE)
|
||||
|
||||
/* Initialize a table */
|
||||
DstTable *dst_table_init(DstTable *table, int32_t capacity) {
|
||||
DstValue *data;
|
||||
if (capacity < 2) capacity = 2;
|
||||
data = calloc(sizeof(DstValue), capacity);
|
||||
data = (DstValue *) dst_memalloc_empty(capacity);
|
||||
if (NULL == data) {
|
||||
DST_OUT_OF_MEMORY;
|
||||
}
|
||||
@ -51,7 +53,7 @@ DstTable *dst_table(int32_t capacity) {
|
||||
/* Find the bucket that contains the given key. Will also return
|
||||
* bucket where key should go if not in the table. */
|
||||
static DstValue *dst_table_find(DstTable *t, DstValue key) {
|
||||
int32_t index = (dst_hash(key) % t->capacity) & (~1);
|
||||
int32_t index = dst_table_maphash(t->capacity, dst_hash(key));
|
||||
int32_t i, j;
|
||||
int32_t start[2], end[2];
|
||||
start[0] = index; end[0] = t->capacity;
|
||||
@ -74,7 +76,7 @@ static DstValue *dst_table_find(DstTable *t, DstValue key) {
|
||||
/* Resize the dictionary table. */
|
||||
static void dst_table_rehash(DstTable *t, int32_t size) {
|
||||
DstValue *olddata = t->data;
|
||||
DstValue *newdata = calloc(sizeof(DstValue), size);
|
||||
DstValue *newdata = (DstValue *) dst_memalloc_empty(size);
|
||||
if (NULL == newdata) {
|
||||
DST_OUT_OF_MEMORY;
|
||||
}
|
||||
@ -179,3 +181,5 @@ const DstValue *dst_table_to_struct(DstTable *t) {
|
||||
}
|
||||
return dst_struct_end(st);
|
||||
}
|
||||
|
||||
#undef dst_table_maphash
|
||||
|
@ -30,12 +30,12 @@ DstValue *dst_tuple_begin(int32_t length) {
|
||||
char *data = dst_alloc(DST_MEMORY_TUPLE, 2 * sizeof(int32_t) + length * sizeof(DstValue));
|
||||
DstValue *tuple = (DstValue *)(data + (2 * sizeof(int32_t)));
|
||||
dst_tuple_length(tuple) = length;
|
||||
dst_tuple_hash(tuple) = 0;
|
||||
return tuple;
|
||||
}
|
||||
|
||||
/* Finish building a tuple */
|
||||
const DstValue *dst_tuple_end(DstValue *tuple) {
|
||||
dst_tuple_hash(tuple) = dst_array_calchash(tuple, dst_tuple_length(tuple));
|
||||
return (const DstValue *)tuple;
|
||||
}
|
||||
|
||||
@ -53,14 +53,14 @@ int dst_tuple_equal(const DstValue *lhs, const DstValue *rhs) {
|
||||
int32_t rlen = dst_tuple_length(rhs);
|
||||
int32_t lhash = dst_tuple_hash(lhs);
|
||||
int32_t rhash = dst_tuple_hash(rhs);
|
||||
if (llen != rlen)
|
||||
return 0;
|
||||
if (lhash == 0)
|
||||
lhash = dst_tuple_hash(lhs) = dst_array_calchash(lhs, llen);
|
||||
if (rhash == 0)
|
||||
rhash = dst_tuple_hash(rhs) = dst_array_calchash(rhs, rlen);
|
||||
if (lhash != rhash)
|
||||
return 0;
|
||||
if (llen != rlen)
|
||||
return 0;
|
||||
for (index = 0; index < llen; index++) {
|
||||
if (!dst_equals(lhs[index], rhs[index]))
|
||||
return 0;
|
||||
|
12
core/value.c
12
core/value.c
@ -73,18 +73,10 @@ int32_t dst_hash(DstValue x) {
|
||||
hash = dst_string_hash(dst_unwrap_string(x));
|
||||
break;
|
||||
case DST_TUPLE:
|
||||
if (0 == dst_tuple_hash(dst_unwrap_tuple(x)))
|
||||
hash = dst_tuple_hash(dst_unwrap_tuple(x)) =
|
||||
dst_array_calchash(dst_unwrap_tuple(x), dst_tuple_length(dst_unwrap_tuple(x)));
|
||||
else
|
||||
hash = dst_tuple_hash(dst_unwrap_tuple(x));
|
||||
hash = dst_tuple_hash(dst_unwrap_tuple(x));
|
||||
break;
|
||||
case DST_STRUCT:
|
||||
if (0 == dst_struct_hash(dst_unwrap_struct(x)))
|
||||
hash = dst_struct_hash(dst_unwrap_struct(x)) =
|
||||
dst_array_calchash(dst_unwrap_struct(x), dst_struct_capacity(dst_unwrap_struct(x)));
|
||||
else
|
||||
hash = dst_struct_hash(dst_unwrap_struct(x));
|
||||
hash = dst_struct_hash(dst_unwrap_struct(x));
|
||||
break;
|
||||
default:
|
||||
if (sizeof(double) == sizeof(void *)) {
|
||||
|
32
core/wrap.c
32
core/wrap.c
@ -24,7 +24,7 @@
|
||||
|
||||
#ifdef DST_NANBOX
|
||||
|
||||
void *dst_nanbox_to_pointer(dst_t x) {
|
||||
void *dst_nanbox_to_pointer(DstValue x) {
|
||||
/* We need to do this shift to keep the higher bits of the pointer
|
||||
* the same as bit 47 as required by the x86 architecture. We may save
|
||||
* an instruction if we do x.u64 & DST_NANBOX_POINTERBITS, but this 0s
|
||||
@ -41,6 +41,14 @@ DstValue dst_nanbox_from_pointer(void *p, uint64_t tagmask) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
DstValue dst_nanbox_from_cpointer(const void *p, uint64_t tagmask) {
|
||||
DstValue ret;
|
||||
ret.cpointer = p;
|
||||
ret.u64 &= DST_NANBOX_POINTERBITS;
|
||||
ret.u64 |= tagmask;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DstValue dst_nanbox_from_double(double d) {
|
||||
DstValue ret;
|
||||
ret.real = d;
|
||||
@ -51,13 +59,23 @@ DstValue dst_nanbox_from_double(double d) {
|
||||
}
|
||||
|
||||
DstValue dst_nanbox_from_bits(uint64_t bits) {
|
||||
dst_t ret;
|
||||
DstValue ret;
|
||||
ret.u64 = bits;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dst_nanbox_memempty(DstValue *mem, uint32_t count) {
|
||||
uint32_t i;
|
||||
void *dst_nanbox_memalloc_empty(int32_t count) {
|
||||
int32_t i;
|
||||
void *mem = malloc(count * sizeof(DstValue));
|
||||
DstValue *mmem = (DstValue *)mem;
|
||||
for (i = 0; i < count; i++) {
|
||||
mmem[i] = dst_wrap_nil();
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
void dst_nanbox_memempty(DstValue *mem, int32_t count) {
|
||||
int32_t i;
|
||||
for (i = 0; i < count; i++) {
|
||||
mem[i] = dst_wrap_nil();
|
||||
}
|
||||
@ -74,24 +92,28 @@ void dst_nanbox_memempty(DstValue *mem, uint32_t count) {
|
||||
DstValue dst_wrap_nil() {
|
||||
DstValue y;
|
||||
y.type = DST_NIL;
|
||||
y.as.u64 = 0;
|
||||
return y;
|
||||
}
|
||||
|
||||
DstValue dst_wrap_true() {
|
||||
DstValue y;
|
||||
y.type = DST_TRUE;
|
||||
y.as.u64 = 0;
|
||||
return y;
|
||||
}
|
||||
|
||||
DstValue dst_wrap_false() {
|
||||
DstValue y;
|
||||
y.type = DST_TRUE;
|
||||
y.type = DST_FALSE;
|
||||
y.as.u64 = 0;
|
||||
return y;
|
||||
}
|
||||
|
||||
DstValue dst_wrap_boolean(int x) {
|
||||
DstValue y;
|
||||
y.type = x ? DST_TRUE : DST_FALSE;
|
||||
y.as.u64 = 0;
|
||||
return y;
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,8 @@
|
||||
* ands crashing (the parser). Instead, error out. */
|
||||
#define DST_RECURSION_GUARD 1000
|
||||
|
||||
/* #define DST_NANBOX */
|
||||
|
||||
#ifdef DST_NANBOX
|
||||
typedef union DstValue DstValue;
|
||||
#else
|
||||
@ -171,10 +173,13 @@ typedef enum DstType {
|
||||
|
||||
#ifdef DST_NANBOX
|
||||
|
||||
#include <math.h>
|
||||
|
||||
union DstValue {
|
||||
uint64_t u64;
|
||||
int64_t i64;
|
||||
void *pointer;
|
||||
const void *cpointer;
|
||||
double real;
|
||||
};
|
||||
|
||||
@ -228,11 +233,14 @@ union DstValue {
|
||||
|
||||
void *dst_nanbox_to_pointer(DstValue x);
|
||||
void dst_nanbox_memempty(DstValue *mem, int32_t count);
|
||||
void *dst_nanbox_memalloc_empty(int32_t count);
|
||||
DstValue dst_nanbox_from_pointer(void *p, uint64_t tagmask);
|
||||
DstValue dst_nanbox_from_cpointer(const void *p, uint64_t tagmask);
|
||||
DstValue dst_nanbox_from_double(double d);
|
||||
DstValue dst_nanbox_from_bits(uint64_t bits);
|
||||
|
||||
#define dst_memempty dst_nanbox_memempty
|
||||
#define dst_memempty(mem, len) dst_nanbox_memempty((mem), (len))
|
||||
#define dst_memalloc_empty(count) dst_nanbox_memalloc_empty(count)
|
||||
|
||||
/* Todo - check for single mask operation */
|
||||
#define dst_truthy(x) \
|
||||
@ -244,6 +252,9 @@ DstValue dst_nanbox_from_bits(uint64_t bits);
|
||||
#define dst_nanbox_wrap_(p, t) \
|
||||
dst_nanbox_from_pointer((p), dst_nanbox_tag(t) | 0x7FF8000000000000lu)
|
||||
|
||||
#define dst_nanbox_wrap_c(p, t) \
|
||||
dst_nanbox_from_cpointer((p), dst_nanbox_tag(t) | 0x7FF8000000000000lu)
|
||||
|
||||
/* Wrap the simple types */
|
||||
#define dst_wrap_nil() dst_nanbox_from_payload(DST_NIL, 1)
|
||||
#define dst_wrap_true() dst_nanbox_from_payload(DST_TRUE, 1)
|
||||
@ -260,14 +271,14 @@ DstValue dst_nanbox_from_bits(uint64_t bits);
|
||||
#define dst_unwrap_real(x) ((x).real)
|
||||
|
||||
/* Wrap the pointer types */
|
||||
#define dst_wrap_struct(s) dst_nanbox_wrap_((s), DST_STRUCT)
|
||||
#define dst_wrap_tuple(s) dst_nanbox_wrap_((s), DST_TUPLE)
|
||||
#define dst_wrap_struct(s) dst_nanbox_wrap_c((s), DST_STRUCT)
|
||||
#define dst_wrap_tuple(s) dst_nanbox_wrap_c((s), DST_TUPLE)
|
||||
#define dst_wrap_fiber(s) dst_nanbox_wrap_((s), DST_FIBER)
|
||||
#define dst_wrap_array(s) dst_nanbox_wrap_((s), DST_ARRAY)
|
||||
#define dst_wrap_table(s) dst_nanbox_wrap_((s), DST_TABLE)
|
||||
#define dst_wrap_buffer(s) dst_nanbox_wrap_((s), DST_BUFFER)
|
||||
#define dst_wrap_string(s) dst_nanbox_wrap_((s), DST_STRING)
|
||||
#define dst_wrap_symbol(s) dst_nanbox_wrap_((s), DST_SYMBOL)
|
||||
#define dst_wrap_string(s) dst_nanbox_wrap_c((s), DST_STRING)
|
||||
#define dst_wrap_symbol(s) dst_nanbox_wrap_c((s), DST_SYMBOL)
|
||||
#define dst_wrap_userdata(s) dst_nanbox_wrap_((s), DST_USERDATA)
|
||||
#define dst_wrap_function(s) dst_nanbox_wrap_((s), DST_FUNCTION)
|
||||
#define dst_wrap_cfunction(s) dst_nanbox_wrap_((s), DST_CFUNCTION)
|
||||
@ -303,6 +314,7 @@ struct DstValue {
|
||||
|
||||
#define dst_u64(x) ((x).as.u64)
|
||||
#define dst_memempty(mem, count) memset((mem), 0, sizeof(DstValue) * (count))
|
||||
#define dst_memalloc_empty(count) calloc((count), sizeof(DstValue))
|
||||
#define dst_type(x) ((x).type)
|
||||
#define dst_checktype(x, t) ((x).type == (t))
|
||||
#define dst_truthy(x) \
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
|
||||
int main() {
|
||||
int64_t i;
|
||||
int32_t i;
|
||||
dst_init();
|
||||
DstArray *array = dst_array(10);
|
||||
assert(array->capacity == 10);
|
||||
@ -11,7 +11,8 @@ int main() {
|
||||
for (i = 0; i < 500; ++i)
|
||||
dst_array_push(array, dst_wrap_integer(i));
|
||||
for (i = 0; i < 500; ++i)
|
||||
assert(array->data[i].type == DST_INTEGER && array->data[i].as.integer == i);
|
||||
assert(dst_checktype(array->data[i], DST_INTEGER) &&
|
||||
dst_unwrap_integer(array->data[i]) == i);
|
||||
for (i = 0; i < 200; ++i)
|
||||
dst_array_pop(array);
|
||||
assert(array->count == 300);
|
||||
|
@ -7,6 +7,8 @@ int main() {
|
||||
DstAssembleResult ares;
|
||||
DstFunction *func;
|
||||
|
||||
printf("sizeof(DstValue) = %lu\n", sizeof(DstValue));
|
||||
|
||||
FILE *f = fopen("./dsts/minimal.dsts", "rb");
|
||||
fseek(f, 0, SEEK_END);
|
||||
long fsize = ftell(f);
|
||||
@ -30,6 +32,7 @@ int main() {
|
||||
assert(pres.status == DST_PARSE_OK);
|
||||
dst_puts(dst_formatc("\nparse result: %v\n\n", pres.result.value));
|
||||
|
||||
/*
|
||||
opts.flags = 0;
|
||||
opts.source = pres.result.value;
|
||||
opts.parsemap = dst_wrap_nil();
|
||||
@ -45,6 +48,9 @@ int main() {
|
||||
|
||||
dst_run(dst_wrap_function(func));
|
||||
dst_puts(dst_formatc("result: %v\n", dst_vm_fiber->ret));
|
||||
*/
|
||||
|
||||
dst_deinit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ int main() {
|
||||
pres = dst_parsec("'(+ 1 () [] 3 5 :hello \"hi\\h41\")");
|
||||
|
||||
assert(pres.status == DST_PARSE_OK);
|
||||
assert(pres.result.value.type == DST_TUPLE);
|
||||
assert(dst_checktype(pres.result.value, DST_TUPLE));
|
||||
|
||||
str = dst_to_string(pres.result.value);
|
||||
printf("%.*s\n", dst_string_length(str), (const char *) str);
|
||||
|
Loading…
Reference in New Issue
Block a user