1
0
mirror of https://github.com/janet-lang/janet synced 2024-06-27 15:43:17 +00:00

WIP integrating nanbox support back into code.

This commit is contained in:
Calvin Rose 2017-11-28 18:27:55 -05:00
parent d84cc5342e
commit b568a6bc88
19 changed files with 982 additions and 796 deletions

View File

@ -23,7 +23,8 @@
#include <dst/dst.h> #include <dst/dst.h>
/* Iniializes an array */ /* Iniializes an array */
DstArray *dst_array_init(DstArray *array, uint32_t capacity) { DstArray *dst_array_init(DstArray *array, int32_t capacity) {
if (capacity < 0) capacity = 0;
DstValue *data = (DstValue *) malloc(sizeof(DstValue) * capacity); DstValue *data = (DstValue *) malloc(sizeof(DstValue) * capacity);
if (NULL == data) { if (NULL == data) {
DST_OUT_OF_MEMORY; DST_OUT_OF_MEMORY;
@ -39,13 +40,13 @@ void dst_array_deinit(DstArray *array) {
} }
/* Creates a new array */ /* Creates a new array */
DstArray *dst_array(uint32_t capacity) { DstArray *dst_array(int32_t capacity) {
DstArray *array = dst_alloc(DST_MEMORY_ARRAY, sizeof(DstArray)); DstArray *array = dst_alloc(DST_MEMORY_ARRAY, sizeof(DstArray));
return dst_array_init(array, capacity); return dst_array_init(array, capacity);
} }
/* Ensure the array has enough capacity for elements */ /* Ensure the array has enough capacity for elements */
void dst_array_ensure(DstArray *array, uint32_t capacity) { void dst_array_ensure(DstArray *array, int32_t capacity) {
DstValue *newData; DstValue *newData;
DstValue *old = array->data; DstValue *old = array->data;
if (capacity <= array->capacity) return; if (capacity <= array->capacity) return;
@ -58,19 +59,18 @@ void dst_array_ensure(DstArray *array, uint32_t capacity) {
} }
/* Set the count of an array. Extend with nil if needed. */ /* Set the count of an array. Extend with nil if needed. */
void dst_array_setcount(DstArray *array, uint32_t count) { void dst_array_setcount(DstArray *array, int32_t count) {
if (count > array->count) { if (count > array->count) {
uint32_t i;
dst_array_ensure(array, count + 1); dst_array_ensure(array, count + 1);
for (i = array->count; i < count; ++i) dst_memempty(array->data + array->count, count - array->count);
array->data[i].type = DST_NIL;
} }
array->count = count; if (count > 0)
array->count = count;
} }
/* Push a value to the top of the array */ /* Push a value to the top of the array */
void dst_array_push(DstArray *array, DstValue x) { void dst_array_push(DstArray *array, DstValue x) {
uint32_t newcount = array->count + 1; int32_t newcount = array->count + 1;
if (newcount >= array->capacity) { if (newcount >= array->capacity) {
dst_array_ensure(array, newcount * 2); dst_array_ensure(array, newcount * 2);
} }

View File

@ -93,8 +93,8 @@ struct DstAssembler {
jmp_buf on_error; jmp_buf on_error;
const uint8_t *errmessage; const uint8_t *errmessage;
uint32_t environments_capacity; int32_t environments_capacity;
uint32_t bytecode_count; /* Used for calculating labels */ int32_t bytecode_count; /* Used for calculating labels */
DstTable labels; /* symbol -> bytecode index */ DstTable labels; /* symbol -> bytecode index */
DstTable constants; /* symbol -> constant index */ DstTable constants; /* symbol -> constant index */
@ -169,8 +169,8 @@ static const DstInstructionDef dst_ops[] = {
/* Compare a DST string to a native 0 terminated c string. Used in the /* Compare a DST string to a native 0 terminated c string. Used in the
* binary search for the instruction definition. */ * binary search for the instruction definition. */
static int dst_strcompare(const uint8_t *str, const char *other) { static int dst_strcompare(const uint8_t *str, const char *other) {
uint32_t len = dst_string_length(str); int32_t len = dst_string_length(str);
uint32_t index; int32_t index;
for (index = 0; index < len; index++) { for (index = 0; index < len; index++) {
uint8_t c = str[index]; uint8_t c = str[index];
uint8_t k = ((const uint8_t *)other)[index]; uint8_t k = ((const uint8_t *)other)[index];
@ -201,11 +201,11 @@ static const DstInstructionDef *dst_findi(const uint8_t *key) {
/* Check a dst string against a bunch of test_strings. Return the /* Check a dst string against a bunch of test_strings. Return the
* index of the matching test_string, or -1 if not found. */ * index of the matching test_string, or -1 if not found. */
static int strsearch(const uint8_t *str, const char **test_strings) { static int32_t strsearch(const uint8_t *str, const char **test_strings) {
uint32_t len = dst_string_length(str); int32_t len = dst_string_length(str);
int index; int index;
for (index = 0; ; index++) { for (index = 0; ; index++) {
uint32_t i; int32_t i;
const char *testword = test_strings[index]; const char *testword = test_strings[index];
if (NULL == testword) if (NULL == testword)
break; break;
@ -243,8 +243,8 @@ static void dst_asm_errorv(DstAssembler *a, const uint8_t *m) {
/* Parse an argument to an assembly instruction, and return the result as an /* Parse an argument to an assembly instruction, and return the result as an
* integer. This integer will need to be trimmed and bound checked. */ * integer. This integer will need to be trimmed and bound checked. */
static int64_t doarg_1(DstAssembler *a, DstOpArgType argtype, DstValue x) { static int32_t doarg_1(DstAssembler *a, DstOpArgType argtype, DstValue x) {
int64_t ret = -1; int32_t ret = -1;
DstTable *c; DstTable *c;
switch (argtype) { switch (argtype) {
case DST_OAT_SLOT: case DST_OAT_SLOT:
@ -267,20 +267,21 @@ static int64_t doarg_1(DstAssembler *a, DstOpArgType argtype, DstValue x) {
c = &a->labels; c = &a->labels;
break; break;
} }
switch (x.type) { switch (dst_type(x)) {
default: default:
goto error; goto error;
break; break;
case DST_INTEGER: case DST_INTEGER:
ret = x.as.integer; ret = dst_unwrap_integer(x);
break; break;
case DST_TUPLE: case DST_TUPLE:
{ {
const DstValue *t = dst_unwrap_tuple(x);
if (argtype == DST_OAT_TYPE) { if (argtype == DST_OAT_TYPE) {
int32_t i = 0;
ret = 0; ret = 0;
uint32_t i = 0; for (i = 0; i < dst_tuple_length(t); i++) {
for (i = 0; i < dst_tuple_length(x.as.tuple); i++) { ret |= doarg_1(a, DST_OAT_SIMPLETYPE, t[i]);
ret |= doarg_1(a, DST_OAT_SIMPLETYPE, x.as.tuple[i]);
} }
} else { } else {
goto error; goto error;
@ -288,24 +289,22 @@ static int64_t doarg_1(DstAssembler *a, DstOpArgType argtype, DstValue x) {
break; break;
} }
case DST_SYMBOL: case DST_SYMBOL:
case DST_STRING:
{ {
x.type = DST_SYMBOL;
if (NULL != c) { if (NULL != c) {
DstValue result = dst_table_get(c, x); DstValue result = dst_table_get(c, x);
if (result.type == DST_INTEGER) { if (dst_checktype(result, DST_INTEGER)) {
if (argtype == DST_OAT_LABEL) { if (argtype == DST_OAT_LABEL) {
ret = result.as.integer - a->bytecode_count; ret = dst_unwrap_integer(result) - a->bytecode_count;
} else { } else {
ret = result.as.integer; ret = dst_unwrap_integer(result);
} }
} else { } else {
dst_asm_errorv(a, dst_formatc("unknown name %q", x)); dst_asm_errorv(a, dst_formatc("unknown name %q", x));
} }
} else if (argtype == DST_OAT_TYPE || argtype == DST_OAT_SIMPLETYPE) { } else if (argtype == DST_OAT_TYPE || argtype == DST_OAT_SIMPLETYPE) {
int index = strsearch(x.as.string, dst_type_names); int32_t index = strsearch(dst_unwrap_symbol(x), dst_type_names);
if (index != -1) { if (index != -1) {
ret = (int64_t) index; ret = index;
} else { } else {
dst_asm_errorv(a, dst_formatc("unknown type %q", x)); dst_asm_errorv(a, dst_formatc("unknown type %q", x));
} }
@ -316,7 +315,7 @@ static int64_t doarg_1(DstAssembler *a, DstOpArgType argtype, DstValue x) {
} }
} }
if (argtype == DST_OAT_SLOT && ret >= a->def->slotcount) if (argtype == DST_OAT_SLOT && ret >= a->def->slotcount)
a->def->slotcount = (uint32_t) ret + 1; a->def->slotcount = (int32_t) ret + 1;
return ret; return ret;
error: error:
@ -333,18 +332,18 @@ static uint32_t doarg(
int nbytes, int nbytes,
int hassign, int hassign,
DstValue x) { DstValue x) {
int64_t arg = doarg_1(a, argtype, x); int32_t arg = doarg_1(a, argtype, x);
/* Calculate the min and max values that can be stored given /* Calculate the min and max values that can be stored given
* nbytes, and whether or not the storage is signed */ * nbytes, and whether or not the storage is signed */
int64_t min = (-hassign) << ((nbytes << 3) - 1); int32_t min = (-hassign) << ((nbytes << 3) - 1);
int64_t max = ~((-1) << ((nbytes << 3) - hassign)); int32_t max = ~((-1) << ((nbytes << 3) - hassign));
if (arg < min) if (arg < min)
dst_asm_errorv(a, dst_formatc("instruction argument %v is too small, must be %d byte%s", dst_asm_errorv(a, dst_formatc("instruction argument %v is too small, must be %d byte%s",
x, nbytes, nbytes > 1 ? "s" : "")); x, nbytes, nbytes > 1 ? "s" : ""));
if (arg > max) if (arg > max)
dst_asm_errorv(a, dst_formatc("instruction argument %v is too large, must be %d byte%s", dst_asm_errorv(a, dst_formatc("instruction argument %v is too large, must be %d byte%s",
x, nbytes, nbytes > 1 ? "s" : "")); x, nbytes, nbytes > 1 ? "s" : ""));
return ((uint32_t) (arg & 0xFFFFFFFF)) << (nth << 3); return ((uint32_t) arg) << (nth << 3);
} }
/* Provide parsing methods for the different kinds of arguments */ /* Provide parsing methods for the different kinds of arguments */
@ -456,15 +455,15 @@ static uint32_t read_instruction(DstAssembler *a, const DstInstructionDef *idef,
* to reference outer function environments, and may change the outer environment. * to reference outer function environments, and may change the outer environment.
* Returns the index of the environment in the assembler's environments, or -1 * Returns the index of the environment in the assembler's environments, or -1
* if not found. */ * if not found. */
static int64_t dst_asm_addenv(DstAssembler *a, DstValue envname) { static int32_t dst_asm_addenv(DstAssembler *a, DstValue envname) {
DstValue check; DstValue check;
DstFuncDef *def = a->def; DstFuncDef *def = a->def;
uint32_t oldlen; int32_t oldlen;
int64_t res; int64_t res;
/* Check for memoized value */ /* Check for memoized value */
check = dst_table_get(&a->envs, envname); check = dst_table_get(&a->envs, envname);
if (check.type != DST_NIL) { if (!dst_checktype(check, DST_NIL)) {
return check.as.integer; return dst_unwrap_integer(check);
} }
if (NULL == a->parent) { if (NULL == a->parent) {
return -1; return -1;
@ -475,24 +474,24 @@ static int64_t dst_asm_addenv(DstAssembler *a, DstValue envname) {
oldlen = def->environments_length; oldlen = def->environments_length;
dst_table_put(&a->envs, envname, dst_wrap_integer(def->environments_length)); dst_table_put(&a->envs, envname, dst_wrap_integer(def->environments_length));
if (oldlen >= a->environments_capacity) { if (oldlen >= a->environments_capacity) {
uint32_t newcap = 2 + 2 * oldlen; int32_t newcap = 2 + 2 * oldlen;
def->environments = realloc(def->environments, newcap * sizeof(uint32_t)); def->environments = realloc(def->environments, newcap * sizeof(int32_t));
if (NULL == def->environments) { if (NULL == def->environments) {
DST_OUT_OF_MEMORY; DST_OUT_OF_MEMORY;
} }
a->environments_capacity = newcap; a->environments_capacity = newcap;
} }
def->environments[def->environments_length++] = (uint32_t) res; def->environments[def->environments_length++] = (int32_t) res;
return (int64_t) oldlen; return (int32_t) oldlen;
} }
/* Helper to assembly. Return the assembly result */ /* Helper to assembly. Return the assembly result */
static DstAssembleResult dst_asm1(DstAssembler *parent, DstAssembleOptions opts) { static DstAssembleResult dst_asm1(DstAssembler *parent, DstAssembleOptions opts) {
DstAssembleResult result; DstAssembleResult result;
DstAssembler a; DstAssembler a;
const DstValue *st = opts.source.as.st; const DstValue *st = dst_unwrap_struct(opts.source);
DstFuncDef *def; DstFuncDef *def;
uint32_t count, i; int32_t count, i;
const DstValue *arr; const DstValue *arr;
DstValue x; DstValue x;
@ -530,25 +529,26 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, DstAssembleOptions opts)
return result; return result;
} }
dst_asm_assert(&a, opts.source.type == DST_STRUCT, "expected struct for assembly source"); dst_asm_assert(&a, dst_checktype(opts.source, DST_STRUCT), "expected struct for assembly source");
/* Set function arity */ /* Set function arity */
x = dst_struct_get(st, dst_csymbolv("arity")); x = dst_struct_get(st, dst_csymbolv("arity"));
def->arity = x.type == DST_INTEGER ? x.as.integer : 0; def->arity = dst_checktype(x, DST_INTEGER) ? dst_unwrap_integer(x) : 0;
/* Create slot aliases */ /* Create slot aliases */
x = dst_struct_get(st, dst_csymbolv("slots")); x = dst_struct_get(st, dst_csymbolv("slots"));
if (dst_seq_view(x, &arr, &count)) { if (dst_seq_view(x, &arr, &count)) {
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
DstValue v = arr[i]; DstValue v = arr[i];
if (v.type == DST_TUPLE) { if (dst_checktype(v, DST_TUPLE)) {
uint32_t j; const DstValue *t = dst_unwrap_tuple(v);
for (j = 0; j < dst_tuple_length(v.as.tuple); j++) { int32_t j;
if (v.as.tuple[j].type != DST_SYMBOL) for (j = 0; j < dst_tuple_length(t); j++) {
if (!dst_checktype(t[j], DST_SYMBOL))
dst_asm_error(&a, "slot names must be symbols"); dst_asm_error(&a, "slot names must be symbols");
dst_table_put(&a.slots, v.as.tuple[j], dst_wrap_integer(i)); dst_table_put(&a.slots, t[j], dst_wrap_integer(i));
} }
} else if (v.type == DST_SYMBOL) { } else if (dst_checktype(v, DST_SYMBOL)) {
dst_table_put(&a.slots, v, dst_wrap_integer(i)); dst_table_put(&a.slots, v, dst_wrap_integer(i));
} else { } else {
dst_asm_error(&a, "slot names must be symbols or tuple of symbols"); dst_asm_error(&a, "slot names must be symbols or tuple of symbols");
@ -560,7 +560,7 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, DstAssembleOptions opts)
x = dst_struct_get(st, dst_csymbolv("environments")); x = dst_struct_get(st, dst_csymbolv("environments"));
if (dst_seq_view(x, &arr, &count)) { if (dst_seq_view(x, &arr, &count)) {
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
dst_asm_assert(&a, arr[i].type == DST_SYMBOL, "environment must be a symbol"); dst_asm_assert(&a, dst_checktype(arr[i], DST_SYMBOL), "environment must be a symbol");
if (dst_asm_addenv(&a, arr[i]) < 0) { if (dst_asm_addenv(&a, arr[i]) < 0) {
dst_asm_error(&a, "environment not found"); dst_asm_error(&a, "environment not found");
} }
@ -577,18 +577,19 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, DstAssembleOptions opts)
} }
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
DstValue ct = arr[i]; DstValue ct = arr[i];
if (ct.type == DST_TUPLE && if (dst_checktype(ct, DST_TUPLE) &&
dst_tuple_length(ct.as.tuple) > 1 && dst_tuple_length(dst_unwrap_tuple(ct)) > 1 &&
ct.as.tuple[0].type == DST_SYMBOL) { dst_checktype(dst_unwrap_tuple(ct)[0], DST_SYMBOL)) {
uint32_t tcount = dst_tuple_length(ct.as.tuple); const DstValue *t = dst_unwrap_tuple(ct);
const uint8_t *macro = ct.as.tuple[0].as.string; int32_t tcount = dst_tuple_length(t);
const uint8_t *macro = dst_unwrap_symbol(t[0]);
if (0 == dst_strcompare(macro, "quote")) { if (0 == dst_strcompare(macro, "quote")) {
def->constants[i] = ct.as.tuple[1]; def->constants[i] = t[1];
} else if (tcount == 3 && } else if (tcount == 3 &&
ct.as.tuple[1].type == DST_SYMBOL && dst_checktype(t[1], DST_SYMBOL) &&
0 == dst_strcompare(macro, "def")) { 0 == dst_strcompare(macro, "def")) {
def->constants[i] = ct.as.tuple[2]; def->constants[i] = t[2];
dst_table_put(&a.constants, ct.as.tuple[1], dst_wrap_integer(i)); dst_table_put(&a.constants, t[1], dst_wrap_integer(i));
} else { } else {
dst_asm_errorv(&a, dst_formatc("could not parse constant \"%v\"", ct)); dst_asm_errorv(&a, dst_formatc("could not parse constant \"%v\"", ct));
} }
@ -606,12 +607,12 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, DstAssembleOptions opts)
x = dst_struct_get(st, dst_csymbolv("bytecode")); x = dst_struct_get(st, dst_csymbolv("bytecode"));
if (dst_seq_view(x, &arr, &count)) { if (dst_seq_view(x, &arr, &count)) {
/* Do labels and find length */ /* Do labels and find length */
uint32_t blength = 0; int32_t blength = 0;
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
DstValue instr = arr[i]; DstValue instr = arr[i];
if (instr.type == DST_SYMBOL) { if (dst_checktype(instr, DST_SYMBOL)) {
dst_table_put(&a.labels, instr, dst_wrap_integer(blength)); dst_table_put(&a.labels, instr, dst_wrap_integer(blength));
} else if (instr.type == DST_TUPLE) { } else if (dst_checktype(instr, DST_TUPLE)) {
blength++; blength++;
} else { } else {
dst_asm_error(&a, "expected assembly instruction"); dst_asm_error(&a, "expected assembly instruction");
@ -619,28 +620,30 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, DstAssembleOptions opts)
} }
/* Allocate bytecode array */ /* Allocate bytecode array */
def->bytecode_length = blength; def->bytecode_length = blength;
def->bytecode = malloc(sizeof(uint32_t) * blength); def->bytecode = malloc(sizeof(int32_t) * blength);
if (NULL == def->bytecode) { if (NULL == def->bytecode) {
DST_OUT_OF_MEMORY; DST_OUT_OF_MEMORY;
} }
/* Do bytecode */ /* Do bytecode */
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
DstValue instr = arr[i]; DstValue instr = arr[i];
if (instr.type == DST_SYMBOL) { if (dst_checktype(instr, DST_SYMBOL)) {
continue; continue;
} else { } else {
uint32_t op; uint32_t op;
const DstInstructionDef *idef; const DstInstructionDef *idef;
dst_asm_assert(&a, instr.type == DST_TUPLE, "expected tuple"); const DstValue *t;
if (dst_tuple_length(instr.as.tuple) == 0) { dst_asm_assert(&a, dst_checktype(instr, DST_TUPLE), "expected tuple");
t = dst_unwrap_tuple(instr);
if (dst_tuple_length(t) == 0) {
op = 0; op = 0;
} else { } else {
dst_asm_assert(&a, instr.as.tuple[0].type == DST_SYMBOL, dst_asm_assert(&a, dst_checktype(t[0], DST_SYMBOL),
"expected symbol in assembly instruction"); "expected symbol in assembly instruction");
idef = dst_findi(instr.as.tuple[0].as.string); idef = dst_findi(dst_unwrap_symbol(t[0]));
if (NULL == idef) if (NULL == idef)
dst_asm_errorv(&a, dst_formatc("unknown instruction %v", instr)); dst_asm_errorv(&a, dst_formatc("unknown instruction %v", instr));
op = read_instruction(&a, idef, instr.as.tuple); op = read_instruction(&a, idef, t);
} }
def->bytecode[a.bytecode_count++] = op; def->bytecode[a.bytecode_count++] = op;
} }
@ -652,7 +655,7 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, DstAssembleOptions opts)
/* Finish everything and return funcdef */ /* Finish everything and return funcdef */
dst_asm_deinit(&a); dst_asm_deinit(&a);
def->environments = def->environments =
realloc(def->environments, def->environments_length * sizeof(uint32_t)); realloc(def->environments, def->environments_length * sizeof(int32_t));
result.result.def = def; result.result.def = def;
result.status = DST_ASSEMBLE_OK; result.status = DST_ASSEMBLE_OK;
return result; return result;

View File

@ -23,7 +23,7 @@
#include <dst/dst.h> #include <dst/dst.h>
/* Initialize a buffer */ /* Initialize a buffer */
DstBuffer *dst_buffer_init(DstBuffer *buffer, uint32_t capacity) { DstBuffer *dst_buffer_init(DstBuffer *buffer, int32_t capacity) {
uint8_t *data = NULL; uint8_t *data = NULL;
if (capacity > 0) { if (capacity > 0) {
data = malloc(sizeof(uint8_t) * capacity); data = malloc(sizeof(uint8_t) * capacity);
@ -43,13 +43,13 @@ void dst_buffer_deinit(DstBuffer *buffer) {
} }
/* Initialize a buffer */ /* Initialize a buffer */
DstBuffer *dst_buffer(uint32_t capacity) { DstBuffer *dst_buffer(int32_t capacity) {
DstBuffer *buffer = dst_alloc(DST_MEMORY_BUFFER, sizeof(DstBuffer)); DstBuffer *buffer = dst_alloc(DST_MEMORY_BUFFER, sizeof(DstBuffer));
return dst_buffer_init(buffer, capacity); return dst_buffer_init(buffer, capacity);
} }
/* Ensure that the buffer has enough internal capacity */ /* Ensure that the buffer has enough internal capacity */
void dst_buffer_ensure(DstBuffer *buffer, uint32_t capacity) { void dst_buffer_ensure(DstBuffer *buffer, int32_t capacity) {
uint8_t *new_data; uint8_t *new_data;
uint8_t *old = buffer->data; uint8_t *old = buffer->data;
if (capacity <= buffer->capacity) return; if (capacity <= buffer->capacity) return;
@ -63,10 +63,10 @@ void dst_buffer_ensure(DstBuffer *buffer, uint32_t capacity) {
/* Adds capacity for enough extra bytes to the buffer. Ensures that the /* Adds capacity for enough extra bytes to the buffer. Ensures that the
* next n bytes pushed to the buffer will not cause a reallocation */ * next n bytes pushed to the buffer will not cause a reallocation */
void dst_buffer_extra(DstBuffer *buffer, uint32_t n) { void dst_buffer_extra(DstBuffer *buffer, int32_t n) {
uint32_t new_size = buffer->count + n; int32_t new_size = buffer->count + n;
if (new_size > buffer->capacity) { if (new_size > buffer->capacity) {
uint32_t new_capacity = new_size * 2; int32_t new_capacity = new_size * 2;
uint8_t *new_data = realloc(buffer->data, new_capacity * sizeof(uint8_t)); uint8_t *new_data = realloc(buffer->data, new_capacity * sizeof(uint8_t));
if (NULL == new_data) { if (NULL == new_data) {
DST_OUT_OF_MEMORY; DST_OUT_OF_MEMORY;
@ -77,8 +77,8 @@ void dst_buffer_extra(DstBuffer *buffer, uint32_t n) {
} }
/* Push multiple bytes into the buffer */ /* Push multiple bytes into the buffer */
void dst_buffer_push_bytes(DstBuffer *buffer, const uint8_t *string, uint32_t length) { void dst_buffer_push_bytes(DstBuffer *buffer, const uint8_t *string, int32_t length) {
uint32_t new_size = buffer->count + length; int32_t new_size = buffer->count + length;
dst_buffer_ensure(buffer, new_size); dst_buffer_ensure(buffer, new_size);
memcpy(buffer->data + buffer->count, string, length); memcpy(buffer->data + buffer->count, string, length);
buffer->count = new_size; buffer->count = new_size;
@ -86,14 +86,14 @@ void dst_buffer_push_bytes(DstBuffer *buffer, const uint8_t *string, uint32_t le
/* Push a cstring to buffer */ /* Push a cstring to buffer */
void dst_buffer_push_cstring(DstBuffer *buffer, const char *cstring) { void dst_buffer_push_cstring(DstBuffer *buffer, const char *cstring) {
uint32_t len = 0; int32_t len = 0;
while (cstring[len]) ++len; while (cstring[len]) ++len;
dst_buffer_push_bytes(buffer, (const uint8_t *) cstring, len); dst_buffer_push_bytes(buffer, (const uint8_t *) cstring, len);
} }
/* Push a single byte to the buffer */ /* Push a single byte to the buffer */
void dst_buffer_push_u8(DstBuffer *buffer, uint8_t byte) { void dst_buffer_push_u8(DstBuffer *buffer, uint8_t byte) {
uint32_t new_size = buffer->count + 1; int32_t new_size = buffer->count + 1;
dst_buffer_ensure(buffer, new_size); dst_buffer_ensure(buffer, new_size);
buffer->data[buffer->count] = byte; buffer->data[buffer->count] = byte;
buffer->count = new_size; buffer->count = new_size;
@ -101,7 +101,7 @@ void dst_buffer_push_u8(DstBuffer *buffer, uint8_t byte) {
/* Push a 16 bit unsigned integer to the buffer */ /* Push a 16 bit unsigned integer to the buffer */
void dst_buffer_push_u16(DstBuffer *buffer, uint16_t x) { void dst_buffer_push_u16(DstBuffer *buffer, uint16_t x) {
uint32_t new_size = buffer->count + 1; int32_t new_size = buffer->count + 1;
dst_buffer_ensure(buffer, new_size); dst_buffer_ensure(buffer, new_size);
buffer->data[buffer->count] = x & 0xFF; buffer->data[buffer->count] = x & 0xFF;
buffer->data[buffer->count + 1] = (x >> 8) & 0xFF; buffer->data[buffer->count + 1] = (x >> 8) & 0xFF;
@ -110,7 +110,7 @@ void dst_buffer_push_u16(DstBuffer *buffer, uint16_t x) {
/* Push a 32 bit unsigned integer to the buffer */ /* Push a 32 bit unsigned integer to the buffer */
void dst_buffer_push_u32(DstBuffer *buffer, uint32_t x) { void dst_buffer_push_u32(DstBuffer *buffer, uint32_t x) {
uint32_t new_size = buffer->count + 4; int32_t new_size = buffer->count + 4;
dst_buffer_ensure(buffer, new_size); dst_buffer_ensure(buffer, new_size);
buffer->data[buffer->count] = x & 0xFF; buffer->data[buffer->count] = x & 0xFF;
buffer->data[buffer->count + 1] = (x >> 8) & 0xFF; buffer->data[buffer->count + 1] = (x >> 8) & 0xFF;
@ -121,7 +121,7 @@ void dst_buffer_push_u32(DstBuffer *buffer, uint32_t x) {
/* Push a 64 bit unsigned integer to the buffer */ /* Push a 64 bit unsigned integer to the buffer */
void dst_buffer_push_u64(DstBuffer *buffer, uint64_t x) { void dst_buffer_push_u64(DstBuffer *buffer, uint64_t x) {
uint32_t new_size = buffer->count + 8; int32_t new_size = buffer->count + 8;
dst_buffer_ensure(buffer, new_size); dst_buffer_ensure(buffer, new_size);
buffer->data[buffer->count] = x & 0xFF; buffer->data[buffer->count] = x & 0xFF;
buffer->data[buffer->count + 1] = (x >> 8) & 0xFF; buffer->data[buffer->count + 1] = (x >> 8) & 0xFF;

View File

@ -23,7 +23,7 @@
#include <dst/dst.h> #include <dst/dst.h>
/* Initialize a new fiber */ /* Initialize a new fiber */
DstFiber *dst_fiber(uint32_t capacity) { DstFiber *dst_fiber(int32_t capacity) {
DstFiber *fiber = dst_alloc(DST_MEMORY_FIBER, sizeof(DstFiber)); DstFiber *fiber = dst_alloc(DST_MEMORY_FIBER, sizeof(DstFiber));
fiber->capacity = capacity; fiber->capacity = capacity;
if (capacity) { if (capacity) {
@ -51,7 +51,7 @@ DstFiber *dst_fiber_reset(DstFiber *fiber) {
} }
/* Ensure that the fiber has enough extra capacity */ /* Ensure that the fiber has enough extra capacity */
void dst_fiber_setcapacity(DstFiber *fiber, uint32_t n) { void dst_fiber_setcapacity(DstFiber *fiber, int32_t n) {
DstValue *newData = realloc(fiber->data, sizeof(DstValue) * n); DstValue *newData = realloc(fiber->data, sizeof(DstValue) * n);
if (NULL == newData) { if (NULL == newData) {
DST_OUT_OF_MEMORY; DST_OUT_OF_MEMORY;
@ -70,7 +70,7 @@ void dst_fiber_push(DstFiber *fiber, DstValue x) {
/* Push 2 values on the next stack frame */ /* Push 2 values on the next stack frame */
void dst_fiber_push2(DstFiber *fiber, DstValue x, DstValue y) { void dst_fiber_push2(DstFiber *fiber, DstValue x, DstValue y) {
uint32_t newtop = fiber->stacktop + 2; int32_t newtop = fiber->stacktop + 2;
if (newtop > fiber->capacity) { if (newtop > fiber->capacity) {
dst_fiber_setcapacity(fiber, 2 * newtop); dst_fiber_setcapacity(fiber, 2 * newtop);
} }
@ -81,7 +81,7 @@ void dst_fiber_push2(DstFiber *fiber, DstValue x, DstValue y) {
/* Push 3 values on the next stack frame */ /* Push 3 values on the next stack frame */
void dst_fiber_push3(DstFiber *fiber, DstValue x, DstValue y, DstValue z) { void dst_fiber_push3(DstFiber *fiber, DstValue x, DstValue y, DstValue z) {
uint32_t newtop = fiber->stacktop + 3; int32_t newtop = fiber->stacktop + 3;
if (newtop > fiber->capacity) { if (newtop > fiber->capacity) {
dst_fiber_setcapacity(fiber, 2 * newtop); dst_fiber_setcapacity(fiber, 2 * newtop);
} }
@ -92,8 +92,8 @@ void dst_fiber_push3(DstFiber *fiber, DstValue x, DstValue y, DstValue z) {
} }
/* Push an array on the next stack frame */ /* Push an array on the next stack frame */
void dst_fiber_pushn(DstFiber *fiber, const DstValue *arr, uint32_t n) { void dst_fiber_pushn(DstFiber *fiber, const DstValue *arr, int32_t n) {
uint32_t newtop = fiber->stacktop + n; int32_t newtop = fiber->stacktop + n;
if (newtop > fiber->capacity) { if (newtop > fiber->capacity) {
dst_fiber_setcapacity(fiber, 2 * newtop); dst_fiber_setcapacity(fiber, 2 * newtop);
} }
@ -104,8 +104,8 @@ void dst_fiber_pushn(DstFiber *fiber, const DstValue *arr, uint32_t n) {
/* Pop a value off of the stack. Will not destroy a current stack frame. /* Pop a value off of the stack. Will not destroy a current stack frame.
* If there is nothing to pop of of the stack, return nil. */ * If there is nothing to pop of of the stack, return nil. */
DstValue dst_fiber_popvalue(DstFiber *fiber) { DstValue dst_fiber_popvalue(DstFiber *fiber) {
uint32_t newstacktop = fiber->stacktop - 1; int32_t newstacktop = fiber->stacktop - 1;
if (newstacktop < fiber->frametop + DST_FRAME_SIZE) { if (newstacktop < fiber->frametop + (int32_t)(DST_FRAME_SIZE)) {
return dst_wrap_nil(); return dst_wrap_nil();
} }
fiber->stacktop = newstacktop; fiber->stacktop = newstacktop;
@ -116,11 +116,11 @@ DstValue dst_fiber_popvalue(DstFiber *fiber) {
void dst_fiber_funcframe(DstFiber *fiber, DstFunction *func) { void dst_fiber_funcframe(DstFiber *fiber, DstFunction *func) {
DstStackFrame *newframe; DstStackFrame *newframe;
uint32_t i; int32_t i;
uint32_t oldframe = fiber->frame; int32_t oldframe = fiber->frame;
uint32_t nextframe = fiber->frametop + DST_FRAME_SIZE; int32_t nextframe = fiber->frametop + DST_FRAME_SIZE;
uint32_t nextframetop = nextframe + func->def->slotcount; int32_t nextframetop = nextframe + func->def->slotcount;
uint32_t nextstacktop = nextframetop + DST_FRAME_SIZE; int32_t nextstacktop = nextframetop + DST_FRAME_SIZE;
if (fiber->capacity < nextstacktop) { if (fiber->capacity < nextstacktop) {
dst_fiber_setcapacity(fiber, 2 * nextstacktop); dst_fiber_setcapacity(fiber, 2 * nextstacktop);
@ -138,12 +138,12 @@ void dst_fiber_funcframe(DstFiber *fiber, DstFunction *func) {
/* Nil unset locals (Needed for gc correctness) */ /* Nil unset locals (Needed for gc correctness) */
for (i = fiber->stacktop; i < fiber->frametop; ++i) { for (i = fiber->stacktop; i < fiber->frametop; ++i) {
fiber->data[i].type = DST_NIL; fiber->data[i] = dst_wrap_nil();
} }
/* Check varargs */ /* Check varargs */
if (func->def->flags & DST_FUNCDEF_FLAG_VARARG) { if (func->def->flags & DST_FUNCDEF_FLAG_VARARG) {
uint32_t tuplehead = fiber->frame + func->def->arity; int32_t tuplehead = fiber->frame + func->def->arity;
if (tuplehead >= fiber->stacktop) { if (tuplehead >= fiber->stacktop) {
fiber->data[tuplehead] = dst_wrap_tuple(dst_tuple_n(NULL, 0)); fiber->data[tuplehead] = dst_wrap_tuple(dst_tuple_n(NULL, 0));
} else { } else {
@ -159,11 +159,11 @@ void dst_fiber_funcframe(DstFiber *fiber, DstFunction *func) {
/* Create a tail frame for a function */ /* Create a tail frame for a function */
void dst_fiber_funcframe_tail(DstFiber *fiber, DstFunction *func) { void dst_fiber_funcframe_tail(DstFiber *fiber, DstFunction *func) {
uint32_t i; int32_t i;
uint32_t nextframetop = fiber->frame + func->def->slotcount; int32_t nextframetop = fiber->frame + func->def->slotcount;
uint32_t nextstacktop = nextframetop + DST_FRAME_SIZE; int32_t nextstacktop = nextframetop + DST_FRAME_SIZE;
uint32_t size = (fiber->stacktop - fiber->frametop) - DST_FRAME_SIZE; int32_t size = (fiber->stacktop - fiber->frametop) - DST_FRAME_SIZE;
uint32_t argtop = fiber->frame + size; int32_t argtop = fiber->frame + size;
if (fiber->capacity < nextstacktop) { if (fiber->capacity < nextstacktop) {
dst_fiber_setcapacity(fiber, 2 * nextstacktop); dst_fiber_setcapacity(fiber, 2 * nextstacktop);
@ -184,12 +184,12 @@ void dst_fiber_funcframe_tail(DstFiber *fiber, DstFunction *func) {
/* Nil unset locals (Needed for gc correctness) */ /* Nil unset locals (Needed for gc correctness) */
for (i = fiber->frame + size; i < fiber->frametop; ++i) { for (i = fiber->frame + size; i < fiber->frametop; ++i) {
fiber->data[i].type = DST_NIL; fiber->data[i] = dst_wrap_nil();
} }
/* Check varargs */ /* Check varargs */
if (func->def->flags & DST_FUNCDEF_FLAG_VARARG) { if (func->def->flags & DST_FUNCDEF_FLAG_VARARG) {
uint32_t tuplehead = fiber->frame + func->def->arity; int32_t tuplehead = fiber->frame + func->def->arity;
if (tuplehead >= argtop) { if (tuplehead >= argtop) {
fiber->data[tuplehead] = dst_wrap_tuple(dst_tuple_n(NULL, 0)); fiber->data[tuplehead] = dst_wrap_tuple(dst_tuple_n(NULL, 0));
} else { } else {
@ -208,10 +208,10 @@ void dst_fiber_funcframe_tail(DstFiber *fiber, DstFunction *func) {
void dst_fiber_cframe(DstFiber *fiber) { void dst_fiber_cframe(DstFiber *fiber) {
DstStackFrame *newframe; DstStackFrame *newframe;
uint32_t oldframe = fiber->frame; int32_t oldframe = fiber->frame;
uint32_t nextframe = fiber->frametop + DST_FRAME_SIZE; int32_t nextframe = fiber->frametop + DST_FRAME_SIZE;
uint32_t nextframetop = fiber->stacktop; int32_t nextframetop = fiber->stacktop;
uint32_t nextstacktop = nextframetop + DST_FRAME_SIZE; int32_t nextstacktop = nextframetop + DST_FRAME_SIZE;
if (fiber->capacity < nextstacktop) { if (fiber->capacity < nextstacktop) {
dst_fiber_setcapacity(fiber, 2 * nextstacktop); dst_fiber_setcapacity(fiber, 2 * nextstacktop);
@ -231,9 +231,9 @@ void dst_fiber_cframe(DstFiber *fiber) {
/* Create a cframe for a tail call */ /* Create a cframe for a tail call */
void dst_fiber_cframe_tail(DstFiber *fiber) { void dst_fiber_cframe_tail(DstFiber *fiber) {
uint32_t size = (fiber->stacktop - fiber->frametop) - DST_FRAME_SIZE; int32_t size = (fiber->stacktop - fiber->frametop) - DST_FRAME_SIZE;
uint32_t nextframetop = fiber->frame + size;; int32_t nextframetop = fiber->frame + size;;
uint32_t nextstacktop = nextframetop + DST_FRAME_SIZE; int32_t nextstacktop = nextframetop + DST_FRAME_SIZE;
if (fiber->frame == 0) { if (fiber->frame == 0) {
return dst_fiber_cframe(fiber); return dst_fiber_cframe(fiber);

View File

@ -43,18 +43,18 @@ static void dst_mark_udata(void *udata);
/* Mark a value */ /* Mark a value */
void dst_mark(DstValue x) { void dst_mark(DstValue x) {
switch (x.type) { switch (dst_type(x)) {
default: break; default: break;
case DST_STRING: case DST_STRING:
case DST_SYMBOL: dst_mark_string(x.as.string); break; case DST_SYMBOL: dst_mark_string(dst_unwrap_string(x)); break;
case DST_FUNCTION: dst_mark_function(x.as.function); break; case DST_FUNCTION: dst_mark_function(dst_unwrap_function(x)); break;
case DST_ARRAY: dst_mark_array(x.as.array); break; case DST_ARRAY: dst_mark_array(dst_unwrap_array(x)); break;
case DST_TABLE: dst_mark_table(x.as.table); break; case DST_TABLE: dst_mark_table(dst_unwrap_table(x)); break;
case DST_STRUCT: dst_mark_struct(x.as.st); break; case DST_STRUCT: dst_mark_struct(dst_unwrap_struct(x)); break;
case DST_TUPLE: dst_mark_tuple(x.as.tuple); break; case DST_TUPLE: dst_mark_tuple(dst_unwrap_tuple(x)); break;
case DST_BUFFER: dst_mark_buffer(x.as.buffer); break; case DST_BUFFER: dst_mark_buffer(dst_unwrap_buffer(x)); break;
case DST_FIBER: dst_mark_fiber(x.as.fiber); break; case DST_FIBER: dst_mark_fiber(dst_unwrap_fiber(x)); break;
case DST_USERDATA: dst_mark_udata(x.as.pointer); break; case DST_USERDATA: dst_mark_udata(dst_unwrap_pointer(x)); break;
} }
} }
@ -65,36 +65,36 @@ void dst_mark(DstValue x) {
* ever saving the table anywhere (except on the c stack, which * ever saving the table anywhere (except on the c stack, which
* the gc cannot inspect). */ * the gc cannot inspect). */
void dst_pin(DstValue x) { void dst_pin(DstValue x) {
switch (x.type) { switch (dst_type(x)) {
default: break; default: break;
case DST_STRING: case DST_STRING:
case DST_SYMBOL: dst_pin_string(x.as.string); break; case DST_SYMBOL: dst_pin_string(dst_unwrap_string(x)); break;
case DST_FUNCTION: dst_pin_function(x.as.function); break; case DST_FUNCTION: dst_pin_function(dst_unwrap_function(x)); break;
case DST_ARRAY: dst_pin_array(x.as.array); break; case DST_ARRAY: dst_pin_array(dst_unwrap_array(x)); break;
case DST_TABLE: dst_pin_table(x.as.table); break; case DST_TABLE: dst_pin_table(dst_unwrap_table(x)); break;
case DST_STRUCT: dst_pin_struct(x.as.st); break; case DST_STRUCT: dst_pin_struct(dst_unwrap_struct(x)); break;
case DST_TUPLE: dst_pin_tuple(x.as.tuple); break; case DST_TUPLE: dst_pin_tuple(dst_unwrap_tuple(x)); break;
case DST_BUFFER: dst_pin_buffer(x.as.buffer); break; case DST_BUFFER: dst_pin_buffer(dst_unwrap_buffer(x)); break;
case DST_FIBER: dst_pin_fiber(x.as.fiber); break; case DST_FIBER: dst_pin_fiber(dst_unwrap_fiber(x)); break;
case DST_USERDATA: dst_pin_userdata(x.as.pointer); break; case DST_USERDATA: dst_pin_userdata(dst_unwrap_pointer(x)); break;
} }
} }
/* Unpin a value. This enables the GC to collect the value's /* Unpin a value. This enables the GC to collect the value's
* memory again. */ * memory again. */
void dst_unpin(DstValue x) { void dst_unpin(DstValue x) {
switch (x.type) { switch (dst_type(x)) {
default: break; default: break;
case DST_STRING: case DST_STRING:
case DST_SYMBOL: dst_unpin_string(x.as.string); break; case DST_SYMBOL: dst_unpin_string(dst_unwrap_string(x)); break;
case DST_FUNCTION: dst_unpin_function(x.as.function); break; case DST_FUNCTION: dst_unpin_function(dst_unwrap_function(x)); break;
case DST_ARRAY: dst_unpin_array(x.as.array); break; case DST_ARRAY: dst_unpin_array(dst_unwrap_array(x)); break;
case DST_TABLE: dst_unpin_table(x.as.table); break; case DST_TABLE: dst_unpin_table(dst_unwrap_table(x)); break;
case DST_STRUCT: dst_unpin_struct(x.as.st); break; case DST_STRUCT: dst_unpin_struct(dst_unwrap_struct(x)); break;
case DST_TUPLE: dst_unpin_tuple(x.as.tuple); break; case DST_TUPLE: dst_unpin_tuple(dst_unwrap_tuple(x)); break;
case DST_BUFFER: dst_unpin_buffer(x.as.buffer); break; case DST_BUFFER: dst_unpin_buffer(dst_unwrap_buffer(x)); break;
case DST_FIBER: dst_unpin_fiber(x.as.fiber); break; case DST_FIBER: dst_unpin_fiber(dst_unwrap_fiber(x)); break;
case DST_USERDATA: dst_unpin_userdata(x.as.pointer); break; case DST_USERDATA: dst_unpin_userdata(dst_unwrap_pointer(x)); break;
} }
} }
@ -111,7 +111,7 @@ static void dst_mark_udata(void *udata) {
} }
/* Mark a bunch of items in memory */ /* Mark a bunch of items in memory */
static void dst_mark_many(const DstValue *values, uint32_t n) { static void dst_mark_many(const DstValue *values, int32_t n) {
const DstValue *end = values + n; const DstValue *end = values + n;
while (values < end) { while (values < end) {
dst_mark(*values); dst_mark(*values);
@ -163,7 +163,7 @@ static void dst_mark_funcenv(DstFuncEnv *env) {
/* GC helper to mark a FuncDef */ /* GC helper to mark a FuncDef */
static void dst_mark_funcdef(DstFuncDef *def) { static void dst_mark_funcdef(DstFuncDef *def) {
uint32_t count, i; int32_t count, i;
if (dst_gc_reachable(def)) if (dst_gc_reachable(def))
return; return;
dst_gc_mark(def); dst_gc_mark(def);
@ -171,9 +171,9 @@ static void dst_mark_funcdef(DstFuncDef *def) {
count = def->constants_length; count = def->constants_length;
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
DstValue v = def->constants[i]; DstValue v = def->constants[i];
/* Funcdefs use boolean literals to store other funcdefs */ /* Funcdefs use nil literals to store other funcdefs */
if (v.type == DST_BOOLEAN) { if (v.type == DST_NIL) {
dst_mark_funcdef((DstFuncDef *) v.as.pointer); dst_mark_funcdef((DstFuncDef *) dst_unwrap_pointer(v));
} else { } else {
dst_mark(v); dst_mark(v);
} }
@ -182,8 +182,8 @@ static void dst_mark_funcdef(DstFuncDef *def) {
} }
static void dst_mark_function(DstFunction *func) { static void dst_mark_function(DstFunction *func) {
uint32_t i; int32_t i;
uint32_t numenvs; int32_t numenvs;
if (dst_gc_reachable(func)) if (dst_gc_reachable(func))
return; return;
dst_gc_mark(func); dst_gc_mark(func);
@ -196,7 +196,7 @@ static void dst_mark_function(DstFunction *func) {
} }
static void dst_mark_fiber(DstFiber *fiber) { static void dst_mark_fiber(DstFiber *fiber) {
uint32_t i, j; int32_t i, j;
DstStackFrame *frame; DstStackFrame *frame;
if (dst_gc_reachable(fiber)) if (dst_gc_reachable(fiber))
return; return;
@ -204,7 +204,7 @@ static void dst_mark_fiber(DstFiber *fiber) {
i = fiber->frame; i = fiber->frame;
j = fiber->frametop; j = fiber->frametop;
while (i != 0) { while (i > 0) {
frame = (DstStackFrame *)(fiber->data + i - DST_FRAME_SIZE); frame = (DstStackFrame *)(fiber->data + i - DST_FRAME_SIZE);
if (NULL != frame->func) if (NULL != frame->func)
dst_mark_function(frame->func); dst_mark_function(frame->func);
@ -228,7 +228,7 @@ static void dst_deinit_block(DstGCMemoryHeader *block) {
default: default:
break; /* Do nothing for non gc types */ break; /* Do nothing for non gc types */
case DST_MEMORY_SYMBOL: case DST_MEMORY_SYMBOL:
dst_symbol_deinit((const uint8_t *)mem + 2 * sizeof(uint32_t)); dst_symbol_deinit((const uint8_t *)mem + 2 * sizeof(int32_t));
break; break;
case DST_MEMORY_ARRAY: case DST_MEMORY_ARRAY:
dst_array_deinit((DstArray*) mem); dst_array_deinit((DstArray*) mem);

View File

@ -172,10 +172,10 @@ typedef struct {
static const uint8_t *parse_recur( static const uint8_t *parse_recur(
ParseArgs *args, ParseArgs *args,
const uint8_t *src, const uint8_t *src,
uint32_t recur) { int32_t recur) {
const uint8_t *end = args->end; const uint8_t *end = args->end;
uint32_t qcount = 0; int32_t qcount = 0;
DstValue ret; DstValue ret;
/* Prevent stack overflow */ /* Prevent stack overflow */
@ -243,7 +243,7 @@ static const uint8_t *parse_recur(
{ {
const uint8_t *strend = ++src; const uint8_t *strend = ++src;
const uint8_t *strstart = strend; const uint8_t *strstart = strend;
uint32_t len = 0; int32_t len = 0;
int containsEscape = 0; int containsEscape = 0;
/* Preprocess string to check for escapes and string end */ /* Preprocess string to check for escapes and string end */
while (strend < end && *strend != '"') { while (strend < end && *strend != '"') {
@ -306,8 +306,8 @@ static const uint8_t *parse_recur(
case '[': case '[':
case '{': case '{':
{ {
uint32_t n = 0, i = 0; int32_t n = 0, i = 0;
uint32_t istable = 0; int32_t istable = 0;
uint8_t close; uint8_t close;
switch (*src++) { switch (*src++) {
case '[': close = ']'; break; case '[': close = ']'; break;
@ -421,7 +421,7 @@ static const uint8_t *parse_recur(
} }
/* Parse an array of bytes. Return value in the fiber return value. */ /* Parse an array of bytes. Return value in the fiber return value. */
DstParseResult dst_parse(const uint8_t *src, uint32_t len) { DstParseResult dst_parse(const uint8_t *src, int32_t len) {
DstParseResult res; DstParseResult res;
ParseArgs args; ParseArgs args;
const uint8_t *newsrc; const uint8_t *newsrc;
@ -433,7 +433,7 @@ DstParseResult dst_parse(const uint8_t *src, uint32_t len) {
newsrc = parse_recur(&args, src, DST_RECURSION_GUARD); newsrc = parse_recur(&args, src, DST_RECURSION_GUARD);
res.status = args.status; res.status = args.status;
res.bytes_read = (uint32_t) (newsrc - src); res.bytes_read = (int32_t) (newsrc - src);
/* TODO - source maps */ /* TODO - source maps */
res.map = dst_wrap_nil(); res.map = dst_wrap_nil();
@ -451,7 +451,7 @@ DstParseResult dst_parse(const uint8_t *src, uint32_t len) {
/* Parse a c string */ /* Parse a c string */
DstParseResult dst_parsec(const char *src) { DstParseResult dst_parsec(const char *src) {
uint32_t len = 0; int32_t len = 0;
while (src[len]) ++len; while (src[len]) ++len;
return dst_parse((const uint8_t *)src, len); return dst_parse((const uint8_t *)src, len);
} }

View File

@ -23,9 +23,9 @@
#include <dst/dst.h> #include <dst/dst.h>
/* Begin building a string */ /* Begin building a string */
uint8_t *dst_string_begin(uint32_t length) { uint8_t *dst_string_begin(int32_t length) {
char *data = dst_alloc(DST_MEMORY_STRING, 2 * sizeof(uint32_t) + length); char *data = dst_alloc(DST_MEMORY_STRING, 2 * sizeof(int32_t) + length);
uint8_t *str = (uint8_t *) (data + 2 * sizeof(uint32_t)); uint8_t *str = (uint8_t *) (data + 2 * sizeof(int32_t));
dst_string_length(str) = length; dst_string_length(str) = length;
return str; return str;
} }
@ -37,10 +37,10 @@ const uint8_t *dst_string_end(uint8_t *str) {
} }
/* Load a buffer as a string */ /* Load a buffer as a string */
const uint8_t *dst_string(const uint8_t *buf, uint32_t len) { const uint8_t *dst_string(const uint8_t *buf, int32_t len) {
uint32_t hash = dst_string_calchash(buf, len); int32_t hash = dst_string_calchash(buf, len);
char *data = dst_alloc(DST_MEMORY_STRING, 2 * sizeof(uint32_t) + len); char *data = dst_alloc(DST_MEMORY_STRING, 2 * sizeof(int32_t) + len);
uint8_t *str = (uint8_t *) (data + 2 * sizeof(uint32_t)); uint8_t *str = (uint8_t *) (data + 2 * sizeof(int32_t));
memcpy(str, buf, len); memcpy(str, buf, len);
dst_string_length(str) = len; dst_string_length(str) = len;
dst_string_hash(str) = hash; dst_string_hash(str) = hash;
@ -49,10 +49,10 @@ const uint8_t *dst_string(const uint8_t *buf, uint32_t len) {
/* Compare two strings */ /* Compare two strings */
int dst_string_compare(const uint8_t *lhs, const uint8_t *rhs) { int dst_string_compare(const uint8_t *lhs, const uint8_t *rhs) {
uint32_t xlen = dst_string_length(lhs); int32_t xlen = dst_string_length(lhs);
uint32_t ylen = dst_string_length(rhs); int32_t ylen = dst_string_length(rhs);
uint32_t len = xlen > ylen ? ylen : xlen; int32_t len = xlen > ylen ? ylen : xlen;
uint32_t i; int32_t i;
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
if (lhs[i] == rhs[i]) { if (lhs[i] == rhs[i]) {
continue; continue;
@ -70,10 +70,10 @@ int dst_string_compare(const uint8_t *lhs, const uint8_t *rhs) {
} }
/* Compare a dst string with a piece of memory */ /* Compare a dst string with a piece of memory */
int dst_string_equalconst(const uint8_t *lhs, const uint8_t *rhs, uint32_t rlen, uint32_t rhash) { int dst_string_equalconst(const uint8_t *lhs, const uint8_t *rhs, int32_t rlen, int32_t rhash) {
uint32_t index; int32_t index;
uint32_t lhash = dst_string_hash(lhs); int32_t lhash = dst_string_hash(lhs);
uint32_t llen = dst_string_length(lhs); int32_t llen = dst_string_length(lhs);
if (lhs == rhs) if (lhs == rhs)
return 1; return 1;
if (lhash != rhash || llen != rlen) if (lhash != rhash || llen != rlen)
@ -93,7 +93,7 @@ int dst_string_equal(const uint8_t *lhs, const uint8_t *rhs) {
/* Load a c string */ /* Load a c string */
const uint8_t *dst_cstring(const char *str) { const uint8_t *dst_cstring(const char *str) {
uint32_t len = 0; int32_t len = 0;
while (str[len]) ++len; while (str[len]) ++len;
return dst_string((const uint8_t *)str, len); return dst_string((const uint8_t *)str, len);
} }
@ -101,9 +101,9 @@ const uint8_t *dst_cstring(const char *str) {
/* Temporary buffer size */ /* Temporary buffer size */
#define DST_BUFSIZE 36 #define DST_BUFSIZE 36
static uint32_t real_to_string_impl(uint8_t *buf, double x) { static int32_t real_to_string_impl(uint8_t *buf, double x) {
int count = snprintf((char *) buf, DST_BUFSIZE, "%.21g", x); int count = snprintf((char *) buf, DST_BUFSIZE, "%.21g", x);
return (uint32_t) count; return (int32_t) count;
} }
static void real_to_string_b(DstBuffer *buffer, double x) { static void real_to_string_b(DstBuffer *buffer, double x) {
@ -116,10 +116,10 @@ static const uint8_t *real_to_string(double x) {
return dst_string(buf, real_to_string_impl(buf, x)); return dst_string(buf, real_to_string_impl(buf, x));
} }
static uint32_t integer_to_string_impl(uint8_t *buf, int64_t x) { static int32_t integer_to_string_impl(uint8_t *buf, int64_t x) {
int neg = 0; int neg = 0;
uint8_t *hi, *low; uint8_t *hi, *low;
uint32_t count = 0; int32_t count = 0;
if (x == 0) { if (x == 0) {
buf[0] = '0'; buf[0] = '0';
return 1; return 1;
@ -160,9 +160,9 @@ static const uint8_t *integer_to_string(int64_t x) {
/* Returns a string description for a pointer. Truncates /* Returns a string description for a pointer. Truncates
* title to 12 characters */ * title to 12 characters */
static uint32_t string_description_impl(uint8_t *buf, const char *title, void *pointer) { static int32_t string_description_impl(uint8_t *buf, const char *title, void *pointer) {
uint8_t *c = buf; uint8_t *c = buf;
uint32_t i; int32_t i;
union { union {
uint8_t bytes[sizeof(void *)]; uint8_t bytes[sizeof(void *)];
void *p; void *p;
@ -182,7 +182,7 @@ static uint32_t string_description_impl(uint8_t *buf, const char *title, void *p
*c++ = HEX(byte & 0xF); *c++ = HEX(byte & 0xF);
} }
*c++ = '>'; *c++ = '>';
return (uint32_t) (c - buf); return (int32_t) (c - buf);
} }
static void string_description_b(DstBuffer *buffer, const char *title, void *pointer) { static void string_description_b(DstBuffer *buffer, const char *title, void *pointer) {
@ -200,9 +200,9 @@ static const uint8_t *string_description(const char *title, void *pointer) {
#undef HEX #undef HEX
#undef DST_BUFSIZE #undef DST_BUFSIZE
static uint32_t dst_escape_string_length(const uint8_t *str) { static int32_t dst_escape_string_length(const uint8_t *str) {
uint32_t len = 2; int32_t len = 2;
uint32_t i; int32_t i;
for (i = 0; i < dst_string_length(str); ++i) { for (i = 0; i < dst_string_length(str); ++i) {
switch (str[i]) { switch (str[i]) {
case '"': case '"':
@ -220,7 +220,7 @@ static uint32_t dst_escape_string_length(const uint8_t *str) {
} }
static void dst_escape_string_impl(uint8_t *buf, const uint8_t *str) { static void dst_escape_string_impl(uint8_t *buf, const uint8_t *str) {
uint32_t i, j; int32_t i, j;
buf[0] = '"'; buf[0] = '"';
for (i = 0, j = 1; i < dst_string_length(str); ++i) { for (i = 0, j = 1; i < dst_string_length(str); ++i) {
uint8_t c = str[i]; uint8_t c = str[i];
@ -250,14 +250,14 @@ static void dst_escape_string_impl(uint8_t *buf, const uint8_t *str) {
} }
void dst_escape_string_b(DstBuffer *buffer, const uint8_t *str) { void dst_escape_string_b(DstBuffer *buffer, const uint8_t *str) {
uint32_t len = dst_escape_string_length(str); int32_t len = dst_escape_string_length(str);
dst_buffer_extra(buffer, len); dst_buffer_extra(buffer, len);
dst_escape_string_impl(buffer->data + buffer->count, str); dst_escape_string_impl(buffer->data + buffer->count, str);
buffer->count += len; buffer->count += len;
} }
const uint8_t *dst_escape_string(const uint8_t *str) { const uint8_t *dst_escape_string(const uint8_t *str) {
uint32_t len = dst_escape_string_length(str); int32_t len = dst_escape_string_length(str);
uint8_t *buf = dst_string_begin(len); uint8_t *buf = dst_string_begin(len);
dst_escape_string_impl(buf, str); dst_escape_string_impl(buf, str);
return dst_string_end(buf); return dst_string_end(buf);
@ -265,57 +265,56 @@ const uint8_t *dst_escape_string(const uint8_t *str) {
/* Returns a string pointer with the description of the string */ /* Returns a string pointer with the description of the string */
const uint8_t *dst_short_description(DstValue x) { const uint8_t *dst_short_description(DstValue x) {
switch (x.type) { switch (dst_type(x)) {
case DST_NIL: case DST_NIL:
return dst_cstring("nil"); return dst_cstring("nil");
case DST_BOOLEAN: case DST_TRUE:
if (x.as.boolean) return dst_cstring("true");
return dst_cstring("true"); case DST_FALSE:
else return dst_cstring("false");
return dst_cstring("false");
case DST_REAL: case DST_REAL:
return real_to_string(x.as.real); return real_to_string(dst_unwrap_real(x));
case DST_INTEGER: case DST_INTEGER:
return integer_to_string(x.as.integer); return integer_to_string(dst_unwrap_integer(x));
case DST_SYMBOL: case DST_SYMBOL:
return x.as.string; return dst_unwrap_string(x);
case DST_STRING: case DST_STRING:
return dst_escape_string(x.as.string); return dst_escape_string(dst_unwrap_string(x));
case DST_USERDATA: case DST_USERDATA:
return string_description(dst_userdata_type(x.as.pointer)->name, x.as.pointer); return string_description(dst_userdata_type(dst_unwrap_pointer(x))->name, dst_unwrap_pointer(x));
default: default:
return string_description(dst_type_names[x.type], x.as.pointer); return string_description(dst_type_names[dst_type(x)], dst_unwrap_pointer(x));
} }
} }
void dst_short_description_b(DstBuffer *buffer, DstValue x) { void dst_short_description_b(DstBuffer *buffer, DstValue x) {
switch (x.type) { switch (dst_type(x)) {
case DST_NIL: case DST_NIL:
dst_buffer_push_cstring(buffer, "nil"); dst_buffer_push_cstring(buffer, "nil");
return; return;
case DST_BOOLEAN: case DST_TRUE:
if (x.as.boolean) dst_buffer_push_cstring(buffer, "true");
dst_buffer_push_cstring(buffer, "true"); return;
else case DST_FALSE:
dst_buffer_push_cstring(buffer, "false"); dst_buffer_push_cstring(buffer, "false");
return; return;
case DST_REAL: case DST_REAL:
real_to_string_b(buffer, x.as.real); real_to_string_b(buffer, dst_unwrap_real(x));
return; return;
case DST_INTEGER: case DST_INTEGER:
integer_to_string_b(buffer, x.as.integer); integer_to_string_b(buffer, dst_unwrap_integer(x));
return; return;
case DST_SYMBOL: case DST_SYMBOL:
dst_buffer_push_bytes(buffer, x.as.string, dst_string_length(x.as.string)); dst_buffer_push_bytes(buffer, dst_unwrap_string(x), dst_string_length(dst_unwrap_string(x)));
return; return;
case DST_STRING: case DST_STRING:
dst_escape_string_b(buffer, x.as.string); dst_escape_string_b(buffer, dst_unwrap_string(x));
return; return;
case DST_USERDATA: case DST_USERDATA:
string_description_b(buffer, dst_userdata_type(x.as.pointer)->name, x.as.pointer); string_description_b(buffer, dst_userdata_type(dst_unwrap_pointer(x))->name, dst_unwrap_pointer(x));
return; return;
default: default:
string_description_b(buffer, dst_type_names[x.type], x.as.pointer); string_description_b(buffer, dst_type_names[dst_type(x)], dst_unwrap_pointer(x));
break; break;
} }
} }
@ -327,10 +326,10 @@ struct DstPrinter {
DstTable seen; DstTable seen;
uint32_t flags; uint32_t flags;
int64_t next; int64_t next;
uint32_t indent; int32_t indent;
uint32_t indent_size; int32_t indent_size;
uint32_t token_line_limit; int32_t token_line_limit;
uint32_t depth; int32_t depth;
}; };
#define DST_PRINTFLAG_INDENT 1 #define DST_PRINTFLAG_INDENT 1
@ -340,7 +339,7 @@ struct DstPrinter {
/* Go to next line for printer */ /* Go to next line for printer */
static void dst_print_indent(DstPrinter *p) { static void dst_print_indent(DstPrinter *p) {
uint32_t i, len; int32_t i, len;
len = p->indent_size * p->indent; len = p->indent_size * p->indent;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
dst_buffer_push_u8(&p->buffer, ' '); dst_buffer_push_u8(&p->buffer, ' ');
@ -349,7 +348,7 @@ static void dst_print_indent(DstPrinter *p) {
/* Check if a value is a print atom (not a printable data structure) */ /* Check if a value is a print atom (not a printable data structure) */
static int is_print_ds(DstValue v) { static int is_print_ds(DstValue v) {
switch (v.type) { switch (dst_type(v)) {
default: return 0; default: return 0;
case DST_ARRAY: case DST_ARRAY:
case DST_STRUCT: case DST_STRUCT:
@ -381,8 +380,8 @@ static const char *dst_type_colors[15] = {
static void dst_description_helper(DstPrinter *p, DstValue x); static void dst_description_helper(DstPrinter *p, DstValue x);
/* Print a hastable view inline */ /* Print a hastable view inline */
static void dst_print_hashtable_inner(DstPrinter *p, const DstValue *data, uint32_t len, uint32_t cap) { static void dst_print_hashtable_inner(DstPrinter *p, const DstValue *data, int32_t len, int32_t cap) {
uint32_t i; int32_t i;
int doindent = 0; int doindent = 0;
if (p->flags & DST_PRINTFLAG_INDENT) { if (p->flags & DST_PRINTFLAG_INDENT) {
if (len <= p->token_line_limit) { if (len <= p->token_line_limit) {
@ -400,7 +399,7 @@ static void dst_print_hashtable_inner(DstPrinter *p, const DstValue *data, uint3
dst_buffer_push_u8(&p->buffer, '\n'); dst_buffer_push_u8(&p->buffer, '\n');
p->indent++; p->indent++;
for (i = 0; i < cap; i += 2) { for (i = 0; i < cap; i += 2) {
if (data[i].type != DST_NIL) { if (dst_checktype(data[i], DST_NIL)) {
dst_print_indent(p); dst_print_indent(p);
dst_description_helper(p, data[i]); dst_description_helper(p, data[i]);
dst_buffer_push_u8(&p->buffer, ' '); dst_buffer_push_u8(&p->buffer, ' ');
@ -413,7 +412,7 @@ static void dst_print_hashtable_inner(DstPrinter *p, const DstValue *data, uint3
} else { } else {
int isfirst = 1; int isfirst = 1;
for (i = 0; i < cap; i += 2) { for (i = 0; i < cap; i += 2) {
if (data[i].type != DST_NIL) { if (dst_checktype(data[i], DST_NIL)) {
if (isfirst) if (isfirst)
isfirst = 0; isfirst = 0;
else else
@ -427,8 +426,8 @@ static void dst_print_hashtable_inner(DstPrinter *p, const DstValue *data, uint3
} }
/* Help print a sequence */ /* Help print a sequence */
static void dst_print_seq_inner(DstPrinter *p, const DstValue *data, uint32_t len) { static void dst_print_seq_inner(DstPrinter *p, const DstValue *data, int32_t len) {
uint32_t i; int32_t i;
int doindent = 0; int doindent = 0;
if (p->flags & DST_PRINTFLAG_INDENT) { if (p->flags & DST_PRINTFLAG_INDENT) {
if (len <= p->token_line_limit) { if (len <= p->token_line_limit) {
@ -465,19 +464,19 @@ static void dst_print_seq_inner(DstPrinter *p, const DstValue *data, uint32_t le
static void dst_description_helper(DstPrinter *p, DstValue x) { static void dst_description_helper(DstPrinter *p, DstValue x) {
p->depth--; p->depth--;
DstValue check = dst_table_get(&p->seen, x); DstValue check = dst_table_get(&p->seen, x);
if (check.type == DST_INTEGER) { if (dst_checktype(check, DST_INTEGER)) {
dst_buffer_push_cstring(&p->buffer, "<cycle "); dst_buffer_push_cstring(&p->buffer, "<cycle ");
integer_to_string_b(&p->buffer, check.as.integer); integer_to_string_b(&p->buffer, dst_unwrap_integer(check));
dst_buffer_push_cstring(&p->buffer, ">"); dst_buffer_push_cstring(&p->buffer, ">");
} else { } else {
const char *open; const char *open;
const char *close; const char *close;
uint32_t len, cap; int32_t len, cap;
const DstValue *data; const DstValue *data;
switch (x.type) { switch (dst_type(x)) {
default: default:
if (p->flags & DST_PRINTFLAG_COLORIZE) { if (p->flags & DST_PRINTFLAG_COLORIZE) {
dst_buffer_push_cstring(&p->buffer, dst_type_colors[x.type]); dst_buffer_push_cstring(&p->buffer, dst_type_colors[dst_type(x)]);
dst_short_description_b(&p->buffer, x); dst_short_description_b(&p->buffer, x);
dst_buffer_push_cstring(&p->buffer, "\x1B[0m"); dst_buffer_push_cstring(&p->buffer, "\x1B[0m");
} else { } else {
@ -547,12 +546,12 @@ const uint8_t *dst_description(DstValue x) {
/* Convert any value to a dst string. Similar to description, but /* Convert any value to a dst string. Similar to description, but
* strings, symbols, and buffers will return their content. */ * strings, symbols, and buffers will return their content. */
const uint8_t *dst_to_string(DstValue x) { const uint8_t *dst_to_string(DstValue x) {
switch (x.type) { switch (dst_type(x)) {
default: default:
return dst_short_description(x); return dst_short_description(x);
case DST_STRING: case DST_STRING:
case DST_SYMBOL: case DST_SYMBOL:
return x.as.string; return dst_unwrap_string(x);
} }
} }
@ -560,8 +559,8 @@ const uint8_t *dst_to_string(DstValue x) {
* Similiar to printf, but specialized for operating with dst. */ * Similiar to printf, but specialized for operating with dst. */
const uint8_t *dst_formatc(const char *format, ...) { const uint8_t *dst_formatc(const char *format, ...) {
va_list args; va_list args;
uint32_t len = 0; int32_t len = 0;
uint32_t i; int32_t i;
const uint8_t *ret; const uint8_t *ret;
DstPrinter printer; DstPrinter printer;
DstBuffer *bufp = &printer.buffer; DstBuffer *bufp = &printer.buffer;
@ -654,8 +653,8 @@ const uint8_t *dst_formatc(const char *format, ...) {
/* Print string to stdout */ /* Print string to stdout */
void dst_puts(const uint8_t *str) { void dst_puts(const uint8_t *str) {
uint32_t i; int32_t i;
uint32_t len = dst_string_length(str); int32_t len = dst_string_length(str);
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
putc(str[i], stdout); putc(str[i], stdout);
} }

View File

@ -23,17 +23,17 @@
#include <dst/dst.h> #include <dst/dst.h>
/* Begin creation of a struct */ /* Begin creation of a struct */
DstValue *dst_struct_begin(uint32_t count) { DstValue *dst_struct_begin(int32_t count) {
/* This expression determines size of structs. It must be a pure /* This expression determines size of structs. It must be a pure
* function of count, and hold at least enough space for count * function of count, and hold at least enough space for count
* key value pairs. The minimum it could be is * key value pairs. The minimum it could be is
* sizeof(uint32_t) * 2 + 2 * count * sizeof(DstValue). Adding more space * sizeof(int32_t) * 2 + 2 * count * sizeof(DstValue). Adding more space
* ensures that structs are less likely to have hash collisions. If 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 */ * is added or s is changed, change the macro dst_struct_capacity in internal.h */
size_t s = sizeof(uint32_t) * 2 + 4 * count * sizeof(DstValue); size_t s = sizeof(int32_t) * 2 + 4 * count * sizeof(DstValue);
char *data = dst_alloc(DST_MEMORY_STRUCT, s); char *data = dst_alloc(DST_MEMORY_STRUCT, s);
memset(data, 0, s); memset(data, 0, s);
DstValue *st = (DstValue *) (data + 2 * sizeof(uint32_t)); DstValue *st = (DstValue *) (data + 2 * sizeof(int32_t));
dst_struct_length(st) = count; dst_struct_length(st) = count;
/* Use the hash storage space as a counter to see how many items /* Use the hash storage space as a counter to see how many items
* were successfully added. If this number is not equal to the * were successfully added. If this number is not equal to the
@ -45,9 +45,9 @@ DstValue *dst_struct_begin(uint32_t count) {
/* Find an item in a struct */ /* Find an item in a struct */
static const DstValue *dst_struct_find(const DstValue *st, DstValue key) { static const DstValue *dst_struct_find(const DstValue *st, DstValue key) {
uint32_t cap = dst_struct_capacity(st); int32_t cap = dst_struct_capacity(st);
uint32_t index = (dst_hash(key) % cap) & (~1); int32_t index = (dst_hash(key) % cap) & (~1);
uint32_t i; int32_t i;
for (i = index; i < cap; i += 2) for (i = index; i < cap; i += 2)
if (st[i].type == DST_NIL || dst_equals(st[i], key)) if (st[i].type == DST_NIL || dst_equals(st[i], key))
return st + i; return st + i;
@ -61,18 +61,19 @@ static const DstValue *dst_struct_find(const DstValue *st, DstValue key) {
* Nil keys and values are ignored, extra keys are ignore, and duplicate keys are * Nil keys and values are ignored, extra keys are ignore, and duplicate keys are
* ignored. */ * ignored. */
void dst_struct_put(DstValue *st, DstValue key, DstValue value) { void dst_struct_put(DstValue *st, DstValue key, DstValue value) {
uint32_t cap = dst_struct_capacity(st); int32_t cap = dst_struct_capacity(st);
uint32_t hash = dst_hash(key); int32_t hash = dst_hash(key);
uint32_t index = (hash % cap) & (~1); int32_t index = (hash % cap) & (~1);
uint32_t i, j, dist; int32_t i, j, dist;
uint32_t bounds[4] = {index, cap, 0, index}; int32_t bounds[4] = {index, cap, 0, index};
if (key.type == DST_NIL || value.type == DST_NIL) return; if (key.type == DST_NIL || value.type == DST_NIL) return;
/* Avoid extra items */ /* Avoid extra items */
if (dst_struct_hash(st) == dst_struct_length(st)) return; if (dst_struct_hash(st) == dst_struct_length(st)) return;
for (dist = 0, j = 0; j < 4; j += 2) for (dist = 0, j = 0; j < 4; j += 2)
for (i = bounds[j]; i < bounds[j + 1]; i += 2, dist += 2) { for (i = bounds[j]; i < bounds[j + 1]; i += 2, dist += 2) {
int status; int status;
uint32_t otherhash, otherindex, otherdist; int32_t otherhash;
int32_t otherindex, otherdist;
/* We found an empty slot, so just add key and value */ /* We found an empty slot, so just add key and value */
if (st[i].type == DST_NIL) { if (st[i].type == DST_NIL) {
st[i] = key; st[i] = key;
@ -126,7 +127,7 @@ const DstValue *dst_struct_end(DstValue *st) {
/* Error building struct, probably duplicate values. We need to rebuild /* Error building struct, probably duplicate values. We need to rebuild
* the struct using only the values that went in. The second creation should always * the struct using only the values that went in. The second creation should always
* succeed. */ * succeed. */
uint32_t i, realCount; int32_t i, realCount;
DstValue *newst; DstValue *newst;
realCount = 0; realCount = 0;
for (i = 0; i < dst_struct_capacity(st); i += 2) { for (i = 0; i < dst_struct_capacity(st); i += 2) {
@ -178,7 +179,7 @@ DstValue dst_struct_next(const DstValue *st, DstValue key) {
/* Convert struct to table */ /* Convert struct to table */
DstTable *dst_struct_to_table(const DstValue *st) { DstTable *dst_struct_to_table(const DstValue *st) {
DstTable *table = dst_table(dst_struct_capacity(st)); DstTable *table = dst_table(dst_struct_capacity(st));
uint32_t i; int32_t i;
for (i = 0; i < dst_struct_capacity(st); i += 2) { for (i = 0; i < dst_struct_capacity(st); i += 2) {
if (st[i].type != DST_NIL) { if (st[i].type != DST_NIL) {
dst_table_put(table, st[i], st[i + 1]); dst_table_put(table, st[i], st[i + 1]);
@ -189,11 +190,11 @@ DstTable *dst_struct_to_table(const DstValue *st) {
/* Check if two structs are equal */ /* Check if two structs are equal */
int dst_struct_equal(const DstValue *lhs, const DstValue *rhs) { int dst_struct_equal(const DstValue *lhs, const DstValue *rhs) {
uint32_t index; int32_t index;
uint32_t llen = dst_struct_capacity(lhs); int32_t llen = dst_struct_capacity(lhs);
uint32_t rlen = dst_struct_capacity(rhs); int32_t rlen = dst_struct_capacity(rhs);
uint32_t lhash = dst_struct_hash(lhs); int32_t lhash = dst_struct_hash(lhs);
uint32_t rhash = dst_struct_hash(rhs); int32_t rhash = dst_struct_hash(rhs);
if (llen != rlen) if (llen != rlen)
return 0; return 0;
if (lhash == 0) if (lhash == 0)
@ -211,11 +212,11 @@ int dst_struct_equal(const DstValue *lhs, const DstValue *rhs) {
/* Compare structs */ /* Compare structs */
int dst_struct_compare(const DstValue *lhs, const DstValue *rhs) { int dst_struct_compare(const DstValue *lhs, const DstValue *rhs) {
uint32_t i; int32_t i;
uint32_t lhash = dst_struct_hash(lhs); int32_t lhash = dst_struct_hash(lhs);
uint32_t rhash = dst_struct_hash(rhs); int32_t rhash = dst_struct_hash(rhs);
uint32_t llen = dst_struct_capacity(lhs); int32_t llen = dst_struct_capacity(lhs);
uint32_t rlen = dst_struct_capacity(rhs); int32_t rlen = dst_struct_capacity(rhs);
if (llen < rlen) if (llen < rlen)
return -1; return -1;
if (llen > rlen) if (llen > rlen)

View File

@ -61,11 +61,11 @@ void dst_symcache_deinit() {
* where one would put it. */ * where one would put it. */
static const uint8_t **dst_symcache_findmem( static const uint8_t **dst_symcache_findmem(
const uint8_t *str, const uint8_t *str,
uint32_t len, int32_t len,
uint32_t hash, int32_t hash,
int *success) { int *success) {
uint32_t bounds[4]; int32_t bounds[4];
uint32_t i, j, index; int32_t i, j, index;
const uint8_t **firstEmpty = NULL; const uint8_t **firstEmpty = NULL;
/* We will search two ranges - index to the end, /* We will search two ranges - index to the end,
@ -110,8 +110,8 @@ static const uint8_t **dst_symcache_findmem(
dst_symcache_findmem((str), dst_string_length(str), dst_string_hash(str), (success)) dst_symcache_findmem((str), dst_string_length(str), dst_string_hash(str), (success))
/* Resize the cache. */ /* Resize the cache. */
static void dst_cache_resize(uint32_t newCapacity) { static void dst_cache_resize(int32_t newCapacity) {
uint32_t i, oldCapacity; int32_t i, oldCapacity;
const uint8_t **oldCache = dst_vm_cache; const uint8_t **oldCache = dst_vm_cache;
const uint8_t **newCache = calloc(1, newCapacity * sizeof(const uint8_t **)); const uint8_t **newCache = calloc(1, newCapacity * sizeof(const uint8_t **));
if (newCache == NULL) { if (newCache == NULL) {
@ -163,15 +163,15 @@ void dst_symbol_deinit(const uint8_t *sym) {
} }
/* Create a symbol from a byte string */ /* Create a symbol from a byte string */
const uint8_t *dst_symbol(const uint8_t *str, uint32_t len) { const uint8_t *dst_symbol(const uint8_t *str, int32_t len) {
uint32_t hash = dst_string_calchash(str, len); int32_t hash = dst_string_calchash(str, len);
uint8_t *newstr; uint8_t *newstr;
int success = 0; int success = 0;
const uint8_t **bucket = dst_symcache_findmem(str, len, hash, &success); const uint8_t **bucket = dst_symcache_findmem(str, len, hash, &success);
if (success) if (success)
return *bucket; return *bucket;
newstr = dst_alloc(DST_MEMORY_SYMBOL, 2 * sizeof(uint32_t) + len) newstr = dst_alloc(DST_MEMORY_SYMBOL, 2 * sizeof(int32_t) + len)
+ (2 * sizeof(uint32_t)); + (2 * sizeof(int32_t));
dst_string_hash(newstr) = hash; dst_string_hash(newstr) = hash;
dst_string_length(newstr) = len; dst_string_length(newstr) = len;
memcpy(newstr, str, len); memcpy(newstr, str, len);
@ -181,7 +181,7 @@ const uint8_t *dst_symbol(const uint8_t *str, uint32_t len) {
/* Get a symbol from a cstring */ /* Get a symbol from a cstring */
const uint8_t *dst_csymbol(const char *cstr) { const uint8_t *dst_csymbol(const char *cstr) {
uint32_t len = 0; int32_t len = 0;
while (cstr[len]) len++; while (cstr[len]) len++;
return dst_symbol((const uint8_t *)cstr, len); return dst_symbol((const uint8_t *)cstr, len);
} }
@ -215,15 +215,15 @@ static void inc_counter(uint8_t *digits, int base, int len) {
/* Generate a unique symbol. This is used in the library function gensym. The /* Generate a unique symbol. This is used in the library function gensym. The
* symbol will be of the format prefix--XXXXXX, where X is a base64 digit, and * symbol will be of the format prefix--XXXXXX, where X is a base64 digit, and
* prefix is the argument passed. */ * prefix is the argument passed. */
const uint8_t *dst_symbol_gen(const uint8_t *buf, uint32_t len) { const uint8_t *dst_symbol_gen(const uint8_t *buf, int32_t len) {
const uint8_t **bucket; const uint8_t **bucket;
uint32_t hash; int32_t hash;
uint8_t counter[6] = {63, 63, 63, 63, 63, 63}; uint8_t counter[6] = {63, 63, 63, 63, 63, 63};
/* Leave spaces for 6 base 64 digits and two dashes. That means 64^6 possible suffixes, which /* Leave spaces for 6 base 64 digits and two dashes. That means 64^6 possible suffixes, which
* is enough for resolving collisions. */ * is enough for resolving collisions. */
uint32_t newlen = len + 8; int32_t newlen = len + 8;
uint32_t newbufsize = newlen + 2 * sizeof(uint32_t); int32_t newbufsize = newlen + 2 * sizeof(int32_t);
uint8_t *str = (uint8_t *)(dst_alloc(DST_MEMORY_SYMBOL, newbufsize) + 2 * sizeof(uint32_t)); uint8_t *str = (uint8_t *)(dst_alloc(DST_MEMORY_SYMBOL, newbufsize) + 2 * sizeof(int32_t));
dst_string_length(str) = newlen; dst_string_length(str) = newlen;
memcpy(str, buf, len); memcpy(str, buf, len);
str[len] = '-'; str[len] = '-';

View File

@ -24,10 +24,10 @@
#include <dst/dst.h> #include <dst/dst.h>
#include <stdio.h> #include <stdio.h>
int dst_sys_print(DstValue *argv, uint32_t argn) { int dst_sys_print(DstValue *argv, int32_t argn) {
uint32_t i; int32_t i;
for (i = 0; i < argn; ++i) { for (i = 0; i < argn; ++i) {
uint32_t j, len; int32_t j, len;
const uint8_t *vstr = dst_to_string(argv[i]); const uint8_t *vstr = dst_to_string(argv[i]);
len = dst_string_length(vstr); len = dst_string_length(vstr);
for (j = 0; j < len; ++j) { for (j = 0; j < len; ++j) {
@ -38,7 +38,7 @@ int dst_sys_print(DstValue *argv, uint32_t argn) {
return 0; return 0;
} }
int dst_sys_asm(DstValue *argv, uint32_t argn) { int dst_sys_asm(DstValue *argv, int32_t argn) {
DstAssembleOptions opts; DstAssembleOptions opts;
DstAssembleResult res; DstAssembleResult res;
if (argn < 1) { if (argn < 1) {
@ -58,12 +58,12 @@ int dst_sys_asm(DstValue *argv, uint32_t argn) {
} }
} }
int dst_sys_tuple(DstValue *argv, uint32_t argn) { int dst_sys_tuple(DstValue *argv, int32_t argn) {
dst_vm_fiber->ret = dst_wrap_tuple(dst_tuple_n(argv, argn)); dst_vm_fiber->ret = dst_wrap_tuple(dst_tuple_n(argv, argn));
return 0; return 0;
} }
int dst_sys_array(DstValue *argv, uint32_t argn) { int dst_sys_array(DstValue *argv, int32_t argn) {
DstArray *array = dst_array(argn); DstArray *array = dst_array(argn);
array->count = argn; array->count = argn;
memcpy(array->data, argv, argn * sizeof(DstValue)); memcpy(array->data, argv, argn * sizeof(DstValue));
@ -71,8 +71,8 @@ int dst_sys_array(DstValue *argv, uint32_t argn) {
return 0; return 0;
} }
int dst_sys_table(DstValue *argv, uint32_t argn) { int dst_sys_table(DstValue *argv, int32_t argn) {
uint32_t i; int32_t i;
DstTable *table = dst_table(argn/2); DstTable *table = dst_table(argn/2);
if (argn & 1) { if (argn & 1) {
dst_vm_fiber->ret = dst_cstringv("expected even number of arguments"); dst_vm_fiber->ret = dst_cstringv("expected even number of arguments");
@ -85,8 +85,8 @@ int dst_sys_table(DstValue *argv, uint32_t argn) {
return 0; return 0;
} }
int dst_sys_struct(DstValue *argv, uint32_t argn) { int dst_sys_struct(DstValue *argv, int32_t argn) {
uint32_t i; int32_t i;
DstValue *st = dst_struct_begin(argn/2); DstValue *st = dst_struct_begin(argn/2);
if (argn & 1) { if (argn & 1) {
dst_vm_fiber->ret = dst_cstringv("expected even number of arguments"); dst_vm_fiber->ret = dst_cstringv("expected even number of arguments");
@ -99,8 +99,8 @@ int dst_sys_struct(DstValue *argv, uint32_t argn) {
return 0; return 0;
} }
int dst_sys_get(DstValue *argv, uint32_t argn) { int dst_sys_get(DstValue *argv, int32_t argn) {
uint32_t i; int32_t i;
DstValue ds; DstValue ds;
if (argn < 1) { if (argn < 1) {
dst_vm_fiber->ret = dst_cstringv("expected at least 1 argument"); dst_vm_fiber->ret = dst_cstringv("expected at least 1 argument");
@ -116,7 +116,7 @@ int dst_sys_get(DstValue *argv, uint32_t argn) {
return 0; return 0;
} }
int dst_sys_put(DstValue *argv, uint32_t argn) { int dst_sys_put(DstValue *argv, int32_t argn) {
DstValue ds, key, value; DstValue ds, key, value;
if (argn < 3) { if (argn < 3) {
dst_vm_fiber->ret = dst_cstringv("expected at least 3 arguments"); dst_vm_fiber->ret = dst_cstringv("expected at least 3 arguments");

View File

@ -23,7 +23,7 @@
#include <dst/dst.h> #include <dst/dst.h>
/* Initialize a table */ /* Initialize a table */
DstTable *dst_table_init(DstTable *table, uint32_t capacity) { DstTable *dst_table_init(DstTable *table, int32_t capacity) {
DstValue *data; DstValue *data;
if (capacity < 2) capacity = 2; if (capacity < 2) capacity = 2;
data = calloc(sizeof(DstValue), capacity); data = calloc(sizeof(DstValue), capacity);
@ -43,7 +43,7 @@ void dst_table_deinit(DstTable *table) {
} }
/* Create a new table */ /* Create a new table */
DstTable *dst_table(uint32_t capacity) { DstTable *dst_table(int32_t capacity) {
DstTable *table = dst_alloc(DST_MEMORY_TABLE, sizeof(DstTable)); DstTable *table = dst_alloc(DST_MEMORY_TABLE, sizeof(DstTable));
return dst_table_init(table, capacity); return dst_table_init(table, capacity);
} }
@ -51,15 +51,15 @@ DstTable *dst_table(uint32_t capacity) {
/* Find the bucket that contains the given key. Will also return /* Find the bucket that contains the given key. Will also return
* bucket where key should go if not in the table. */ * bucket where key should go if not in the table. */
static DstValue *dst_table_find(DstTable *t, DstValue key) { static DstValue *dst_table_find(DstTable *t, DstValue key) {
uint32_t index = (dst_hash(key) % (t->capacity / 2)) * 2; int32_t index = (dst_hash(key) % t->capacity) & (~1);
uint32_t i, j; int32_t i, j;
uint32_t start[2], end[2]; int32_t start[2], end[2];
start[0] = index; end[0] = t->capacity; start[0] = index; end[0] = t->capacity;
start[1] = 0; end[1] = index; start[1] = 0; end[1] = index;
for (j = 0; j < 2; ++j) { for (j = 0; j < 2; ++j) {
for (i = start[j]; i < end[j]; i += 2) { for (i = start[j]; i < end[j]; i += 2) {
if (t->data[i].type == DST_NIL) { if (dst_checktype(t->data[i], DST_NIL)) {
if (t->data[i + 1].type == DST_NIL) { if (dst_checktype(t->data[i + 1], DST_NIL)) {
/* Empty */ /* Empty */
return t->data + i; return t->data + i;
} }
@ -72,19 +72,19 @@ static DstValue *dst_table_find(DstTable *t, DstValue key) {
} }
/* Resize the dictionary table. */ /* Resize the dictionary table. */
static void dst_table_rehash(DstTable *t, uint32_t size) { static void dst_table_rehash(DstTable *t, int32_t size) {
DstValue *olddata = t->data; DstValue *olddata = t->data;
DstValue *newdata = calloc(sizeof(DstValue), size); DstValue *newdata = calloc(sizeof(DstValue), size);
if (NULL == newdata) { if (NULL == newdata) {
DST_OUT_OF_MEMORY; DST_OUT_OF_MEMORY;
} }
uint32_t i, oldcapacity; int32_t i, oldcapacity;
oldcapacity = t->capacity; oldcapacity = t->capacity;
t->data = newdata; t->data = newdata;
t->capacity = size; t->capacity = size;
t->deleted = 0; t->deleted = 0;
for (i = 0; i < oldcapacity; i += 2) { for (i = 0; i < oldcapacity; i += 2) {
if (olddata[i].type != DST_NIL) { if (!dst_checktype(olddata[i], DST_NIL)) {
DstValue *bucket = dst_table_find(t, olddata[i]); DstValue *bucket = dst_table_find(t, olddata[i]);
bucket[0] = olddata[i]; bucket[0] = olddata[i];
bucket[1] = olddata[i + 1]; bucket[1] = olddata[i + 1];
@ -96,7 +96,7 @@ static void dst_table_rehash(DstTable *t, uint32_t size) {
/* Get a value out of the object */ /* Get a value out of the object */
DstValue dst_table_get(DstTable *t, DstValue key) { DstValue dst_table_get(DstTable *t, DstValue key) {
DstValue *bucket = dst_table_find(t, key); DstValue *bucket = dst_table_find(t, key);
if (bucket && bucket[0].type != DST_NIL) if (NULL != bucket && !dst_checktype(bucket[0], DST_NIL))
return bucket[1]; return bucket[1];
else else
return dst_wrap_nil(); return dst_wrap_nil();
@ -106,12 +106,12 @@ DstValue dst_table_get(DstTable *t, DstValue key) {
* was removed. */ * was removed. */
DstValue dst_table_remove(DstTable *t, DstValue key) { DstValue dst_table_remove(DstTable *t, DstValue key) {
DstValue *bucket = dst_table_find(t, key); DstValue *bucket = dst_table_find(t, key);
if (bucket && bucket[0].type != DST_NIL) { if (NULL != bucket && !dst_checktype(bucket[0], DST_NIL)) {
DstValue ret = bucket[1]; DstValue ret = bucket[1];
t->count--; t->count--;
t->deleted++; t->deleted++;
bucket[0].type = DST_NIL; bucket[0] = dst_wrap_nil();
bucket[1].type = DST_BOOLEAN; bucket[1] = dst_wrap_false();
return ret; return ret;
} else { } else {
return dst_wrap_nil(); return dst_wrap_nil();
@ -120,19 +120,19 @@ DstValue dst_table_remove(DstTable *t, DstValue key) {
/* Put a value into the object */ /* Put a value into the object */
void dst_table_put(DstTable *t, DstValue key, DstValue value) { void dst_table_put(DstTable *t, DstValue key, DstValue value) {
if (key.type == DST_NIL) return; if (dst_checktype(key, DST_NIL)) return;
if (value.type == DST_NIL) { if (dst_checktype(value, DST_NIL)) {
dst_table_remove(t, key); dst_table_remove(t, key);
} else { } else {
DstValue *bucket = dst_table_find(t, key); DstValue *bucket = dst_table_find(t, key);
if (bucket && bucket[0].type != DST_NIL) { if (NULL != bucket && !dst_checktype(bucket[0], DST_NIL)) {
bucket[1] = value; bucket[1] = value;
} else { } else {
if (!bucket || 4 * (t->count + t->deleted) >= t->capacity) { if (NULL == bucket || 4 * (t->count + t->deleted) >= t->capacity) {
dst_table_rehash(t, 4 * t->count + 6); dst_table_rehash(t, 4 * t->count + 6);
} }
bucket = dst_table_find(t, key); bucket = dst_table_find(t, key);
if (bucket[1].type == DST_BOOLEAN) if (dst_checktype(bucket[1], DST_FALSE))
--t->deleted; --t->deleted;
bucket[0] = key; bucket[0] = key;
bucket[1] = value; bucket[1] = value;
@ -143,11 +143,9 @@ void dst_table_put(DstTable *t, DstValue key, DstValue value) {
/* Clear a table */ /* Clear a table */
void dst_table_clear(DstTable *t) { void dst_table_clear(DstTable *t) {
uint32_t capacity = t->capacity; int32_t capacity = t->capacity;
uint32_t i;
DstValue *data = t->data; DstValue *data = t->data;
for (i = 0; i < capacity; i += 2) dst_memempty(data, capacity);
data[i].type = DST_NIL;
t->count = 0; t->count = 0;
t->deleted = 0; t->deleted = 0;
} }
@ -156,16 +154,16 @@ void dst_table_clear(DstTable *t) {
DstValue dst_table_next(DstTable *t, DstValue key) { DstValue dst_table_next(DstTable *t, DstValue key) {
const DstValue *bucket, *end; const DstValue *bucket, *end;
end = t->data + t->capacity; end = t->data + t->capacity;
if (key.type == DST_NIL) { if (dst_checktype(key, DST_NIL)) {
bucket = t->data; bucket = t->data;
} else { } else {
bucket = dst_table_find(t, key); bucket = dst_table_find(t, key);
if (!bucket || bucket[0].type == DST_NIL) if (NULL == bucket || dst_checktype(bucket[0], DST_NIL))
return dst_wrap_nil(); return dst_wrap_nil();
bucket += 2; bucket += 2;
} }
for (; bucket < end; bucket += 2) { for (; bucket < end; bucket += 2) {
if (bucket[0].type != DST_NIL) if (!dst_checktype(bucket[0], DST_NIL))
return bucket[0]; return bucket[0];
} }
return dst_wrap_nil(); return dst_wrap_nil();
@ -173,10 +171,10 @@ DstValue dst_table_next(DstTable *t, DstValue key) {
/* Convert table to struct */ /* Convert table to struct */
const DstValue *dst_table_to_struct(DstTable *t) { const DstValue *dst_table_to_struct(DstTable *t) {
uint32_t i; int32_t i;
DstValue *st = dst_struct_begin(t->count); DstValue *st = dst_struct_begin(t->count);
for (i = 0; i < t->capacity; i++) { for (i = 0; i < t->capacity; i++) {
if (t->data[i].type != DST_NIL) if (!dst_checktype(t->data[i], DST_NIL))
dst_struct_put(st, t->data[i], t->data[i + 1]); dst_struct_put(st, t->data[i], t->data[i + 1]);
} }
return dst_struct_end(st); return dst_struct_end(st);

View File

@ -26,9 +26,9 @@
/* Create a new empty tuple of the given size. This will return memory /* Create a new empty tuple of the given size. This will return memory
* which should be filled with DstValues. The memory will not be collected until * which should be filled with DstValues. The memory will not be collected until
* dst_tuple_end is called. */ * dst_tuple_end is called. */
DstValue *dst_tuple_begin(uint32_t length) { DstValue *dst_tuple_begin(int32_t length) {
char *data = dst_alloc(DST_MEMORY_TUPLE, 2 * sizeof(uint32_t) + length * sizeof(DstValue)); char *data = dst_alloc(DST_MEMORY_TUPLE, 2 * sizeof(int32_t) + length * sizeof(DstValue));
DstValue *tuple = (DstValue *)(data + (2 * sizeof(uint32_t))); DstValue *tuple = (DstValue *)(data + (2 * sizeof(int32_t)));
dst_tuple_length(tuple) = length; dst_tuple_length(tuple) = length;
dst_tuple_hash(tuple) = 0; dst_tuple_hash(tuple) = 0;
return tuple; return tuple;
@ -40,7 +40,7 @@ const DstValue *dst_tuple_end(DstValue *tuple) {
} }
/* Build a tuple with n values */ /* Build a tuple with n values */
const DstValue *dst_tuple_n(DstValue *values, uint32_t n) { const DstValue *dst_tuple_n(DstValue *values, int32_t n) {
DstValue *t = dst_tuple_begin(n); DstValue *t = dst_tuple_begin(n);
memcpy(t, values, sizeof(DstValue) * n); memcpy(t, values, sizeof(DstValue) * n);
return dst_tuple_end(t); return dst_tuple_end(t);
@ -48,11 +48,11 @@ const DstValue *dst_tuple_n(DstValue *values, uint32_t n) {
/* Check if two tuples are equal */ /* Check if two tuples are equal */
int dst_tuple_equal(const DstValue *lhs, const DstValue *rhs) { int dst_tuple_equal(const DstValue *lhs, const DstValue *rhs) {
uint32_t index; int32_t index;
uint32_t llen = dst_tuple_length(lhs); int32_t llen = dst_tuple_length(lhs);
uint32_t rlen = dst_tuple_length(rhs); int32_t rlen = dst_tuple_length(rhs);
uint32_t lhash = dst_tuple_hash(lhs); int32_t lhash = dst_tuple_hash(lhs);
uint32_t rhash = dst_tuple_hash(rhs); int32_t rhash = dst_tuple_hash(rhs);
if (llen != rlen) if (llen != rlen)
return 0; return 0;
if (lhash == 0) if (lhash == 0)
@ -70,10 +70,10 @@ int dst_tuple_equal(const DstValue *lhs, const DstValue *rhs) {
/* Compare tuples */ /* Compare tuples */
int dst_tuple_compare(const DstValue *lhs, const DstValue *rhs) { int dst_tuple_compare(const DstValue *lhs, const DstValue *rhs) {
uint32_t i; int32_t i;
uint32_t llen = dst_tuple_length(lhs); int32_t llen = dst_tuple_length(lhs);
uint32_t rlen = dst_tuple_length(rhs); int32_t rlen = dst_tuple_length(rhs);
uint32_t count = llen < rlen ? llen : rlen; int32_t count = llen < rlen ? llen : rlen;
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
int comp = dst_compare(lhs[i], rhs[i]); int comp = dst_compare(lhs[i], rhs[i]);
if (comp != 0) return comp; if (comp != 0) return comp;

View File

@ -23,7 +23,7 @@
#include <dst/dst.h> #include <dst/dst.h>
/* Create new userdata */ /* Create new userdata */
void *dst_userdata(uint32_t size, const DstUserType *utype) { void *dst_userdata(size_t size, const DstUserType *utype) {
char *data = dst_alloc(DST_MEMORY_USERDATA, sizeof(DstUserdataHeader) + size); char *data = dst_alloc(DST_MEMORY_USERDATA, sizeof(DstUserdataHeader) + size);
DstUserdataHeader *header = (DstUserdataHeader *)data; DstUserdataHeader *header = (DstUserdataHeader *)data;
void *user = data + sizeof(DstUserdataHeader); void *user = data + sizeof(DstUserdataHeader);

View File

@ -50,48 +50,48 @@ const char *dst_type_names[15] = {
}; };
/* Computes hash of an array of values */ /* Computes hash of an array of values */
uint32_t dst_array_calchash(const DstValue *array, uint32_t len) { int32_t dst_array_calchash(const DstValue *array, int32_t len) {
const DstValue *end = array + len; const DstValue *end = array + len;
uint32_t hash = 5381; uint32_t hash = 5381;
while (array < end) while (array < end)
hash = (hash << 5) + hash + dst_hash(*array++); hash = (hash << 5) + hash + dst_hash(*array++);
return hash; return (int32_t) hash;
} }
/* Calculate hash for string */ /* Calculate hash for string */
uint32_t dst_string_calchash(const uint8_t *str, uint32_t len) { int32_t dst_string_calchash(const uint8_t *str, int32_t len) {
const uint8_t *end = str + len; const uint8_t *end = str + len;
uint32_t hash = 5381; uint32_t hash = 5381;
while (str < end) while (str < end)
hash = (hash << 5) + hash + *str++; hash = (hash << 5) + hash + *str++;
return hash; return (int32_t) hash;
} }
/* Read both tuples and arrays as c pointers + uint32_t length. Return 1 if the /* Read both tuples and arrays as c pointers + int32_t length. Return 1 if the
* view can be constructed, 0 if an invalid type. */ * view can be constructed, 0 if an invalid type. */
int dst_seq_view(DstValue seq, const DstValue **data, uint32_t *len) { int dst_seq_view(DstValue seq, const DstValue **data, int32_t *len) {
if (seq.type == DST_ARRAY) { if (dst_checktype(seq, DST_ARRAY)) {
*data = seq.as.array->data; *data = dst_unwrap_array(seq)->data;
*len = seq.as.array->count; *len = dst_unwrap_array(seq)->count;
return 1; return 1;
} else if (seq.type == DST_TUPLE) { } else if (dst_checktype(seq, DST_TUPLE)) {
*data = seq.as.st; *data = dst_unwrap_struct(seq);
*len = dst_tuple_length(seq.as.st); *len = dst_tuple_length(dst_unwrap_struct(seq));
return 1; return 1;
} }
return 0; return 0;
} }
/* Read both strings and buffer as unsigned character array + uint32_t len. /* Read both strings and buffer as unsigned character array + int32_t len.
* Returns 1 if the view can be constructed and 0 if the type is invalid. */ * Returns 1 if the view can be constructed and 0 if the type is invalid. */
int dst_chararray_view(DstValue str, const uint8_t **data, uint32_t *len) { int dst_chararray_view(DstValue str, const uint8_t **data, int32_t *len) {
if (str.type == DST_STRING || str.type == DST_SYMBOL) { if (dst_checktype(str, DST_STRING) || dst_checktype(str, DST_SYMBOL)) {
*data = str.as.string; *data = dst_unwrap_string(str);
*len = dst_string_length(str.as.string); *len = dst_string_length(dst_unwrap_string(str));
return 1; return 1;
} else if (str.type == DST_BUFFER) { } else if (dst_checktype(str, DST_BUFFER)) {
*data = str.as.buffer->data; *data = dst_unwrap_buffer(str)->data;
*len = str.as.buffer->count; *len = dst_unwrap_buffer(str)->count;
return 1; return 1;
} }
return 0; return 0;
@ -100,29 +100,17 @@ int dst_chararray_view(DstValue str, const uint8_t **data, uint32_t *len) {
/* Read both structs and tables as the entries of a hashtable with /* Read both structs and tables as the entries of a hashtable with
* identical structure. Returns 1 if the view can be constructed and * identical structure. Returns 1 if the view can be constructed and
* 0 if the type is invalid. */ * 0 if the type is invalid. */
int dst_hashtable_view(DstValue tab, const DstValue **data, uint32_t *len, uint32_t *cap) { int dst_hashtable_view(DstValue tab, const DstValue **data, int32_t *len, int32_t *cap) {
if (tab.type == DST_TABLE) { if (dst_checktype(tab, DST_TABLE)) {
*data = tab.as.table->data; *data = dst_unwrap_table(tab)->data;
*cap = tab.as.table->capacity; *cap = dst_unwrap_table(tab)->capacity;
*len = tab.as.table->count; *len = dst_unwrap_table(tab)->count;
return 1; return 1;
} else if (tab.type == DST_STRUCT) { } else if (dst_checktype(tab, DST_STRUCT)) {
*data = tab.as.st; *data = dst_unwrap_struct(tab);
*cap = dst_struct_capacity(tab.as.st); *cap = dst_struct_capacity(dst_unwrap_struct(tab));
*len = dst_struct_length(tab.as.st); *len = dst_struct_length(dst_unwrap_struct(tab));
return 1; return 1;
} }
return 0; return 0;
} }
/* Convert a real to int */
int64_t dst_real_to_integer(double real) {
/* TODO - consider c undefined behavior */
return (int64_t) real;
}
/* Convert an integer to a real */
double dst_integer_to_real(int64_t integer) {
/* TODO - consider c undefined behavior */
return (double) integer;
}

View File

@ -26,39 +26,33 @@
* Define a number of functions that can be used internally on ANY DstValue. * Define a number of functions that can be used internally on ANY DstValue.
*/ */
/* Boolean truth definition */
int dst_truthy(DstValue v) {
return v.type != DST_NIL && !(v.type == DST_BOOLEAN && !v.as.boolean);
}
/* Check if two values are equal. This is strict equality with no conversion. */ /* Check if two values are equal. This is strict equality with no conversion. */
int dst_equals(DstValue x, DstValue y) { int dst_equals(DstValue x, DstValue y) {
int result = 0; int result = 0;
if (x.type != y.type) { if (dst_type(x) != dst_type(y)) {
result = 0; result = 0;
} else { } else {
switch (x.type) { switch (dst_type(x)) {
case DST_NIL: case DST_NIL:
case DST_TRUE:
case DST_FALSE:
result = 1; result = 1;
break; break;
case DST_BOOLEAN:
result = (x.as.boolean == y.as.boolean);
break;
case DST_REAL: case DST_REAL:
result = (x.as.real == y.as.real); result = (dst_unwrap_real(x) == dst_unwrap_real(y));
break; break;
case DST_INTEGER: case DST_INTEGER:
result = (x.as.integer == y.as.integer); result = (dst_unwrap_integer(x) == dst_unwrap_integer(y));
break; break;
case DST_STRING: case DST_STRING:
result = dst_string_equal(x.as.string, y.as.string); result = dst_string_equal(dst_unwrap_string(x), dst_unwrap_string(y));
break; break;
case DST_STRUCT: case DST_STRUCT:
result = dst_struct_equal(x.as.st, y.as.st); result = dst_struct_equal(dst_unwrap_struct(x), dst_unwrap_struct(y));
break; break;
default: default:
/* compare pointers */ /* compare pointers */
result = (x.as.pointer == y.as.pointer); result = (dst_unwrap_pointer(x) == dst_unwrap_pointer(y));
break; break;
} }
} }
@ -66,41 +60,40 @@ int dst_equals(DstValue x, DstValue y) {
} }
/* Computes a hash value for a function */ /* Computes a hash value for a function */
uint32_t dst_hash(DstValue x) { int32_t dst_hash(DstValue x) {
uint32_t hash = 0; int32_t hash = 0;
switch (x.type) { switch (dst_type(x)) {
case DST_NIL: case DST_NIL:
hash = 0; case DST_FALSE:
break; case DST_TRUE:
case DST_BOOLEAN: hash = dst_type(x);
hash = x.as.boolean;
break; break;
case DST_STRING: case DST_STRING:
case DST_SYMBOL: case DST_SYMBOL:
hash = dst_string_hash(x.as.string); hash = dst_string_hash(dst_unwrap_string(x));
break; break;
case DST_TUPLE: case DST_TUPLE:
if (0 == dst_tuple_hash(x.as.tuple)) if (0 == dst_tuple_hash(dst_unwrap_tuple(x)))
hash = dst_tuple_hash(x.as.tuple) = hash = dst_tuple_hash(dst_unwrap_tuple(x)) =
dst_array_calchash(x.as.tuple, dst_tuple_length(x.as.tuple)); dst_array_calchash(dst_unwrap_tuple(x), dst_tuple_length(dst_unwrap_tuple(x)));
else else
hash = dst_tuple_hash(x.as.tuple); hash = dst_tuple_hash(dst_unwrap_tuple(x));
break; break;
case DST_STRUCT: case DST_STRUCT:
if (0 == dst_struct_hash(x.as.st)) if (0 == dst_struct_hash(dst_unwrap_struct(x)))
hash = dst_struct_hash(x.as.st) = hash = dst_struct_hash(dst_unwrap_struct(x)) =
dst_array_calchash(x.as.st, dst_struct_capacity(x.as.st)); dst_array_calchash(dst_unwrap_struct(x), dst_struct_capacity(dst_unwrap_struct(x)));
else else
hash = dst_struct_hash(x.as.st); hash = dst_struct_hash(dst_unwrap_struct(x));
break; break;
default: default:
if (sizeof(double) == sizeof(void *)) { if (sizeof(double) == sizeof(void *)) {
/* Assuming 8 byte pointer */ /* Assuming 8 byte pointer */
uint64_t i = x.as.integer; uint64_t i = dst_u64(x);
hash = (uint32_t)(i >> 32) ^ (uint32_t)(i & 0xFFFFFFFF); hash = (int32_t)(i >> 32) ^ (int32_t)(i & 0xFFFFFFFF);
} else { } else {
/* Assuming 4 byte pointer (or smaller) */ /* Assuming 4 byte pointer (or smaller) */
hash = (uint32_t) (x.as.pointer - NULL); hash = (int32_t) (dst_unwrap_pointer(x) - NULL);
} }
break; break;
} }
@ -111,51 +104,47 @@ uint32_t dst_hash(DstValue x) {
* If y is less, returns 1. All types are comparable * If y is less, returns 1. All types are comparable
* and should have strict ordering. */ * and should have strict ordering. */
int dst_compare(DstValue x, DstValue y) { int dst_compare(DstValue x, DstValue y) {
if (x.type == y.type) { if (dst_type(x) == dst_type(y)) {
switch (x.type) { switch (dst_type(x)) {
case DST_NIL: case DST_NIL:
case DST_FALSE:
case DST_TRUE:
return 0; return 0;
case DST_BOOLEAN:
if (x.as.boolean == y.as.boolean) {
return 0;
} else {
return x.as.boolean ? 1 : -1;
}
case DST_REAL: case DST_REAL:
/* Check for nans to ensure total order */ /* Check for nans to ensure total order */
if (x.as.real != x.as.real) if (dst_unwrap_real(x) != dst_unwrap_real(x))
return y.as.real != y.as.real return dst_unwrap_real(y) != dst_unwrap_real(y)
? 0 ? 0
: -1; : -1;
if (y.as.real != y.as.real) if (dst_unwrap_real(y) != dst_unwrap_real(y))
return 1; return 1;
if (x.as.real == y.as.real) { if (dst_unwrap_real(x) == dst_unwrap_real(y)) {
return 0; return 0;
} else { } else {
return x.as.real > y.as.real ? 1 : -1; return dst_unwrap_real(x) > dst_unwrap_real(y) ? 1 : -1;
} }
case DST_INTEGER: case DST_INTEGER:
if (x.as.integer == y.as.integer) { if (dst_unwrap_integer(x) == dst_unwrap_integer(y)) {
return 0; return 0;
} else { } else {
return x.as.integer > y.as.integer ? 1 : -1; return dst_unwrap_integer(x) > dst_unwrap_integer(y) ? 1 : -1;
} }
case DST_STRING: case DST_STRING:
return dst_string_compare(x.as.string, y.as.string); return dst_string_compare(dst_unwrap_string(x), dst_unwrap_string(y));
case DST_TUPLE: case DST_TUPLE:
return dst_tuple_compare(x.as.tuple, y.as.tuple); return dst_tuple_compare(dst_unwrap_tuple(x), dst_unwrap_tuple(y));
case DST_STRUCT: case DST_STRUCT:
return dst_struct_compare(x.as.st, y.as.st); return dst_struct_compare(dst_unwrap_struct(x), dst_unwrap_struct(y));
default: default:
if (x.as.string == y.as.string) { if (dst_unwrap_string(x) == dst_unwrap_string(y)) {
return 0; return 0;
} else { } else {
return x.as.string > y.as.string ? 1 : -1; return dst_unwrap_string(x) > dst_unwrap_string(y) ? 1 : -1;
} }
} }
} else if (x.type < y.type) { } else if (dst_type(x) < dst_type(y)) {
return -1; return -1;
} }
return 1; return 1;
@ -164,36 +153,36 @@ int dst_compare(DstValue x, DstValue y) {
/* Get a value out af an associated data structure. For invalid /* Get a value out af an associated data structure. For invalid
* data structure or invalid key, returns nil. */ * data structure or invalid key, returns nil. */
DstValue dst_get(DstValue ds, DstValue key) { DstValue dst_get(DstValue ds, DstValue key) {
switch (ds.type) { switch (dst_type(ds)) {
case DST_ARRAY: case DST_ARRAY:
if (key.type == DST_INTEGER && if (dst_checktype(key, DST_INTEGER) &&
key.as.integer >= 0 && dst_unwrap_integer(key) >= 0 &&
key.as.integer < ds.as.array->count) dst_unwrap_integer(key) < dst_unwrap_array(ds)->count)
return ds.as.array->data[key.as.integer]; return dst_unwrap_array(ds)->data[dst_unwrap_integer(key)];
break; break;
case DST_TUPLE: case DST_TUPLE:
if (key.type == DST_INTEGER && if (dst_checktype(key, DST_INTEGER) &&
key.as.integer >= 0 && dst_unwrap_integer(key) >= 0 &&
key.as.integer < dst_tuple_length(ds.as.tuple)) dst_unwrap_integer(key) < dst_tuple_length(dst_unwrap_tuple(ds)))
return ds.as.tuple[key.as.integer]; return dst_unwrap_tuple(ds)[dst_unwrap_integer(key)];
break; break;
case DST_BUFFER: case DST_BUFFER:
if (key.type == DST_INTEGER && if (dst_checktype(key, DST_INTEGER) &&
key.as.integer >= 0 && dst_unwrap_integer(key) >= 0 &&
key.as.integer < ds.as.buffer->count) dst_unwrap_integer(key) < dst_unwrap_buffer(ds)->count)
return dst_wrap_integer(ds.as.buffer->data[key.as.integer]); return dst_wrap_integer(dst_unwrap_buffer(ds)->data[dst_unwrap_integer(key)]);
break; break;
case DST_STRING: case DST_STRING:
case DST_SYMBOL: case DST_SYMBOL:
if (key.type == DST_INTEGER && if (dst_checktype(key, DST_INTEGER) &&
key.as.integer >= 0 && dst_unwrap_integer(key) >= 0 &&
key.as.integer < dst_string_length(ds.as.string)) dst_unwrap_integer(key) < dst_string_length(dst_unwrap_string(ds)))
return dst_wrap_integer(ds.as.string[key.as.integer]); return dst_wrap_integer(dst_unwrap_string(ds)[dst_unwrap_integer(key)]);
break; break;
case DST_STRUCT: case DST_STRUCT:
return dst_struct_get(ds.as.st, key); return dst_struct_get(dst_unwrap_struct(ds), key);
case DST_TABLE: case DST_TABLE:
return dst_table_get(ds.as.table, key); return dst_table_get(dst_unwrap_table(ds), key);
default: default:
break; break;
} }
@ -203,22 +192,22 @@ DstValue dst_get(DstValue ds, DstValue key) {
/* Set a value in an associative data structure. Returns possible /* Set a value in an associative data structure. Returns possible
* error message, and NULL if no error. */ * error message, and NULL if no error. */
void dst_put(DstValue ds, DstValue key, DstValue value) { void dst_put(DstValue ds, DstValue key, DstValue value) {
switch (ds.type) { switch (dst_type(ds)) {
case DST_ARRAY: case DST_ARRAY:
if (key.type == DST_INTEGER && if (dst_checktype(key, DST_INTEGER) &&
key.as.integer >= 0 && dst_unwrap_integer(key) >= 0 &&
key.as.integer < ds.as.array->count) dst_unwrap_integer(key) < dst_unwrap_array(ds)->count)
ds.as.array->data[key.as.integer] = value; dst_unwrap_array(ds)->data[dst_unwrap_integer(key)] = value;
return; return;
case DST_BUFFER: case DST_BUFFER:
if (key.type == DST_INTEGER && if (dst_checktype(key, DST_INTEGER) &&
value.type == DST_INTEGER && dst_checktype(value, DST_INTEGER) &&
key.as.integer >= 0 && dst_unwrap_integer(key) >= 0 &&
key.as.integer < ds.as.buffer->count) dst_unwrap_integer(key) < dst_unwrap_buffer(ds)->count)
ds.as.buffer->data[key.as.integer] = value.as.integer; dst_unwrap_buffer(ds)->data[dst_unwrap_integer(key)] = dst_unwrap_integer(value);
return; return;
case DST_TABLE: case DST_TABLE:
dst_table_put(ds.as.table, key, value); dst_table_put(dst_unwrap_table(ds), key, value);
return; return;
default: default:
return; return;
@ -228,96 +217,96 @@ void dst_put(DstValue ds, DstValue key, DstValue value) {
/* Get the next key in an associative data structure. Used for iterating through an /* Get the next key in an associative data structure. Used for iterating through an
* associative data structure. */ * associative data structure. */
DstValue dst_next(DstValue ds, DstValue key) { DstValue dst_next(DstValue ds, DstValue key) {
switch(ds.type) { switch(dst_type(ds)) {
default: default:
return dst_wrap_nil(); return dst_wrap_nil();
case DST_TABLE: case DST_TABLE:
return dst_table_next(ds.as.table, key); return dst_table_next(dst_unwrap_table(ds), key);
case DST_STRUCT: case DST_STRUCT:
return dst_struct_next(ds.as.st, key); return dst_struct_next(dst_unwrap_struct(ds), key);
} }
} }
/* Get the length of an object. Returns errors for invalid types */ /* Get the length of an object. Returns errors for invalid types */
uint32_t dst_length(DstValue x) { int32_t dst_length(DstValue x) {
switch (x.type) { switch (dst_type(x)) {
default: default:
return 0; return 0;
case DST_STRING: case DST_STRING:
return dst_string_length(x.as.string); return dst_string_length(dst_unwrap_string(x));
case DST_ARRAY: case DST_ARRAY:
return x.as.array->count; return dst_unwrap_array(x)->count;
case DST_BUFFER: case DST_BUFFER:
return x.as.buffer->count; return dst_unwrap_buffer(x)->count;
case DST_TUPLE: case DST_TUPLE:
return dst_tuple_length(x.as.tuple); return dst_tuple_length(dst_unwrap_tuple(x));
case DST_STRUCT: case DST_STRUCT:
return dst_struct_length(x.as.st); return dst_struct_length(dst_unwrap_struct(x));
case DST_TABLE: case DST_TABLE:
return x.as.table->count; return dst_unwrap_table(x)->count;
} }
} }
/* Get the capacity of an object. Returns 0 for invalid types */ /* Get the capacity of an object. Returns 0 for invalid types */
uint32_t dst_capacity(DstValue x) { int32_t dst_capacity(DstValue x) {
switch (x.type) { switch (dst_type(x)) {
default: default:
return 0; return 0;
case DST_STRING: case DST_STRING:
return dst_string_length(x.as.string); return dst_string_length(dst_unwrap_string(x));
case DST_ARRAY: case DST_ARRAY:
return x.as.array->capacity; return dst_unwrap_array(x)->capacity;
case DST_BUFFER: case DST_BUFFER:
return x.as.buffer->capacity; return dst_unwrap_buffer(x)->capacity;
case DST_TUPLE: case DST_TUPLE:
return dst_tuple_length(x.as.tuple); return dst_tuple_length(dst_unwrap_tuple(x));
case DST_STRUCT: case DST_STRUCT:
return dst_struct_length(x.as.st); return dst_struct_length(dst_unwrap_struct(x));
case DST_TABLE: case DST_TABLE:
return x.as.table->capacity; return dst_unwrap_table(x)->capacity;
} }
} }
/* Index into a data structure. Returns nil for out of bounds or invliad data structure */ /* Index into a data structure. Returns nil for out of bounds or invliad data structure */
DstValue dst_getindex(DstValue ds, uint32_t index) { DstValue dst_getindex(DstValue ds, int32_t index) {
switch (ds.type) { switch (dst_type(ds)) {
default: default:
return dst_wrap_nil(); return dst_wrap_nil();
case DST_STRING: case DST_STRING:
if (index >= dst_string_length(ds.as.string)) return dst_wrap_nil(); if (index >= dst_string_length(dst_unwrap_string(ds))) return dst_wrap_nil();
return dst_wrap_integer(ds.as.string[index]); return dst_wrap_integer(dst_unwrap_string(ds)[index]);
case DST_ARRAY: case DST_ARRAY:
if (index >= ds.as.array->count) return dst_wrap_nil(); if (index >= dst_unwrap_array(ds)->count) return dst_wrap_nil();
return ds.as.array->data[index]; return dst_unwrap_array(ds)->data[index];
case DST_BUFFER: case DST_BUFFER:
if (index >= ds.as.buffer->count) return dst_wrap_nil(); if (index >= dst_unwrap_buffer(ds)->count) return dst_wrap_nil();
return dst_wrap_integer(ds.as.buffer->data[index]); return dst_wrap_integer(dst_unwrap_buffer(ds)->data[index]);
case DST_TUPLE: case DST_TUPLE:
if (index >= dst_tuple_length(ds.as.tuple)) return dst_wrap_nil(); if (index >= dst_tuple_length(dst_unwrap_tuple(ds))) return dst_wrap_nil();
return ds.as.tuple[index]; return dst_unwrap_tuple(ds)[index];
} }
} }
/* Set an index in a linear data structure. Does nothing if data structure /* Set an index in a linear data structure. Does nothing if data structure
* is invalid */ * is invalid */
void dst_setindex(DstValue ds, DstValue value, uint32_t index) { void dst_setindex(DstValue ds, DstValue value, int32_t index) {
switch (ds.type) { switch (dst_type(ds)) {
default: default:
return; return;
case DST_ARRAY: case DST_ARRAY:
if (index >= ds.as.array->count) { if (index >= dst_unwrap_array(ds)->count) {
dst_array_ensure(ds.as.array, 2 * index); dst_array_ensure(dst_unwrap_array(ds), 2 * index);
ds.as.array->count = index + 1; dst_unwrap_array(ds)->count = index + 1;
} }
ds.as.array->data[index] = value; dst_unwrap_array(ds)->data[index] = value;
return; return;
case DST_BUFFER: case DST_BUFFER:
if (value.type != DST_INTEGER) return; if (!dst_checktype(value, DST_INTEGER)) return;
if (index >= ds.as.buffer->count) { if (index >= dst_unwrap_buffer(ds)->count) {
dst_buffer_ensure(ds.as.buffer, 2 * index); dst_buffer_ensure(dst_unwrap_buffer(ds), 2 * index);
ds.as.buffer->count = index + 1; dst_unwrap_buffer(ds)->count = index + 1;
} }
ds.as.buffer->data[index] = value.as.integer; dst_unwrap_buffer(ds)->data[index] = dst_unwrap_integer(value);
return; return;
} }
} }

168
core/vm.c
View File

@ -67,26 +67,26 @@ int dst_continue() {
* Pulls out unsigned integers */ * Pulls out unsigned integers */
#define oparg(shift, mask) (((*pc) >> ((shift) << 3)) & (mask)) #define oparg(shift, mask) (((*pc) >> ((shift) << 3)) & (mask))
#define vm_throw(e) do { dst_vm_fiber->ret = dst_wrap_string(dst_cstring((e))); goto vm_error; } while (0) #define vm_throw(e) do { dst_vm_fiber->ret = dst_cstringv((e)); goto vm_error; } while (0)
#define vm_assert(cond, e) do {if (!(cond)) vm_throw((e)); } while (0) #define vm_assert(cond, e) do {if (!(cond)) vm_throw((e)); } while (0)
#define vm_binop_integer(op) \ #define vm_binop_integer(op) \
stack[oparg(1, 0xFF)] = dst_wrap_integer(\ stack[oparg(1, 0xFF)] = dst_wrap_integer(\
stack[oparg(2, 0xFF)].as.integer op stack[oparg(3, 0xFF)].as.integer\ dst_unwrap_integer(stack[oparg(2, 0xFF)]) op dst_unwrap_integer(stack[oparg(3, 0xFF)])\
);\ );\
pc++;\ pc++;\
vm_next(); vm_next();
#define vm_binop_real(op)\ #define vm_binop_real(op)\
stack[oparg(1, 0xFF)] = dst_wrap_real(\ stack[oparg(1, 0xFF)] = dst_wrap_real(\
stack[oparg(2, 0xFF)].as.real op stack[oparg(3, 0xFF)].as.real\ dst_unwrap_real(stack[oparg(2, 0xFF)]) op dst_unwrap_real(stack[oparg(3, 0xFF)])\
);\ );\
pc++;\ pc++;\
vm_next(); vm_next();
#define vm_binop_immediate(op)\ #define vm_binop_immediate(op)\
stack[oparg(1, 0xFF)] = dst_wrap_integer(\ stack[oparg(1, 0xFF)] = dst_wrap_integer(\
stack[oparg(2, 0xFF)].as.integer op (*((int32_t *)pc) >> 24)\ dst_unwrap_integer(stack[oparg(2, 0xFF)]) op (*((int32_t *)pc) >> 24)\
);\ );\
pc++;\ pc++;\
vm_next(); vm_next();
@ -95,15 +95,15 @@ int dst_continue() {
{\ {\
DstValue op1 = stack[oparg(2, 0xFF)];\ DstValue op1 = stack[oparg(2, 0xFF)];\
DstValue op2 = stack[oparg(3, 0xFF)];\ DstValue op2 = stack[oparg(3, 0xFF)];\
vm_assert(op1.type == DST_INTEGER || op1.type == DST_REAL, "expected number");\ vm_assert(dst_checktype(op1, DST_INTEGER) || dst_checktype(op1, DST_REAL), "expected number");\
vm_assert(op2.type == DST_INTEGER || op2.type == DST_REAL, "expected number");\ vm_assert(dst_checktype(op2, DST_INTEGER) || dst_checktype(op2, DST_REAL), "expected number");\
stack[oparg(1, 0xFF)] = op1.type == DST_INTEGER\ stack[oparg(1, 0xFF)] = dst_checktype(op1, DST_INTEGER)\
? (op2.type == DST_INTEGER\ ? (dst_checktype(op2, DST_INTEGER)\
? dst_wrap_integer(op1.as.integer op op2.as.integer)\ ? dst_wrap_integer(dst_unwrap_integer(op1) op dst_unwrap_integer(op2))\
: dst_wrap_real(dst_integer_to_real(op1.as.integer) op op2.as.real))\ : dst_wrap_real((double)dst_unwrap_integer(op1) op dst_unwrap_real(op2)))\
: (op2.type == DST_INTEGER\ : (dst_checktype(op2, DST_INTEGER)\
? dst_wrap_real(op1.as.real op dst_integer_to_real(op2.as.integer))\ ? dst_wrap_real(dst_unwrap_real(op1) op (double)dst_unwrap_integer(op2))\
: dst_wrap_real(op1.as.real op op2.as.real));\ : dst_wrap_real(dst_unwrap_real(op1) op dst_unwrap_real(op2)));\
pc++;\ pc++;\
vm_next();\ vm_next();\
} }
@ -137,7 +137,7 @@ int dst_continue() {
goto vm_error; goto vm_error;
case DOP_TYPECHECK: case DOP_TYPECHECK:
vm_assert((1 << stack[oparg(1, 0xFF)].type) & oparg(2, 0xFFFF), vm_assert((1 << dst_type(stack[oparg(1, 0xFF)])) & oparg(2, 0xFFFF),
"typecheck failed"); "typecheck failed");
pc++; pc++;
vm_next(); vm_next();
@ -147,7 +147,7 @@ int dst_continue() {
goto vm_return; goto vm_return;
case DOP_RETURN_NIL: case DOP_RETURN_NIL:
dst_vm_fiber->ret.type = DST_NIL; dst_vm_fiber->ret = dst_wrap_nil();
goto vm_return; goto vm_return;
case DOP_ADD_INTEGER: case DOP_ADD_INTEGER:
@ -184,16 +184,16 @@ int dst_continue() {
vm_binop(*); vm_binop(*);
case DOP_DIVIDE_INTEGER: case DOP_DIVIDE_INTEGER:
vm_assert(stack[oparg(3, 0xFF)].as.integer != 0, "integer divide by zero"); vm_assert(dst_unwrap_integer(stack[oparg(3, 0xFF)]) != 0, "integer divide by zero");
vm_assert(!(stack[oparg(3, 0xFF)].as.integer == -1 && vm_assert(!(dst_unwrap_integer(stack[oparg(3, 0xFF)]) == -1 &&
stack[oparg(2, 0xFF)].as.integer == DST_INTEGER_MIN), dst_unwrap_integer(stack[oparg(2, 0xFF)]) == DST_INTEGER_MIN),
"integer divide overflow"); "integer divide overflow");
vm_binop_integer(/); vm_binop_integer(/);
case DOP_DIVIDE_IMMEDIATE: case DOP_DIVIDE_IMMEDIATE:
{ {
int64_t op1 = stack[oparg(2, 0xFF)].as.integer; int32_t op1 = dst_unwrap_integer(stack[oparg(2, 0xFF)]);
int64_t op2 = *((int32_t *)pc) >> 24; int32_t op2 = *((int32_t *)pc) >> 24;
/* Check for degenerate integer division (divide by zero, and dividing /* Check for degenerate integer division (divide by zero, and dividing
* min value by -1). These checks could be omitted if the arg is not * min value by -1). These checks could be omitted if the arg is not
* 0 or -1. */ * 0 or -1. */
@ -214,20 +214,20 @@ int dst_continue() {
{ {
DstValue op1 = stack[oparg(2, 0xFF)]; DstValue op1 = stack[oparg(2, 0xFF)];
DstValue op2 = stack[oparg(3, 0xFF)]; DstValue op2 = stack[oparg(3, 0xFF)];
vm_assert(op1.type == DST_INTEGER || op1.type == DST_REAL, "expected number"); vm_assert(dst_checktype(op1, DST_INTEGER) || dst_checktype(op1, DST_REAL), "expected number");
vm_assert(op2.type == DST_INTEGER || op2.type == DST_REAL, "expected number"); vm_assert(dst_checktype(op2, DST_INTEGER) || dst_checktype(op2, DST_REAL), "expected number");
if (op2.type == DST_INTEGER && op2.as.integer == 0) if (dst_checktype(op2, DST_INTEGER) && dst_unwrap_integer(op2) == 0)
op2 = dst_wrap_real(0.0); op2 = dst_wrap_real(0.0);
if (op2.type == DST_INTEGER && op2.as.integer == -1 && if (dst_checktype(op2, DST_INTEGER) && dst_unwrap_integer(op2) == -1 &&
op1.type == DST_INTEGER && op1.as.integer == DST_INTEGER_MIN) dst_checktype(op1, DST_INTEGER) && dst_unwrap_integer(op1) == DST_INTEGER_MIN)
op2 = dst_wrap_real(-1); op2 = dst_wrap_real(-1.0);
stack[oparg(1, 0xFF)] = op1.type == DST_INTEGER stack[oparg(1, 0xFF)] = dst_checktype(op1, DST_INTEGER)
? op2.type == DST_INTEGER ? (dst_checktype(op2, DST_INTEGER)
? dst_wrap_integer(op1.as.integer / op2.as.integer) ? dst_wrap_integer(dst_unwrap_integer(op1) / dst_unwrap_integer(op2))
: dst_wrap_real(dst_integer_to_real(op1.as.integer) / op2.as.real) : dst_wrap_real((double)dst_unwrap_integer(op1) / dst_unwrap_real(op2)))
: op2.type == DST_INTEGER : (dst_checktype(op2, DST_INTEGER)
? dst_wrap_real(op1.as.real / dst_integer_to_real(op2.as.integer)) ? dst_wrap_real(dst_unwrap_real(op1) / (double)dst_unwrap_integer(op2))
: dst_wrap_real(op1.as.real / op2.as.real); : dst_wrap_real(dst_unwrap_real(op1) / dst_unwrap_real(op2)));
pc++; pc++;
vm_next(); vm_next();
} }
@ -242,21 +242,21 @@ int dst_continue() {
vm_binop_integer(^); vm_binop_integer(^);
case DOP_BNOT: case DOP_BNOT:
stack[oparg(1, 0xFF)] = dst_wrap_integer(~stack[oparg(2, 0xFFFF)].as.integer); stack[oparg(1, 0xFF)] = dst_wrap_integer(~dst_unwrap_integer(stack[oparg(2, 0xFFFF)]));
vm_next(); vm_next();
case DOP_SHIFT_RIGHT_UNSIGNED: case DOP_SHIFT_RIGHT_UNSIGNED:
stack[oparg(1, 0xFF)] = dst_wrap_integer( stack[oparg(1, 0xFF)] = dst_wrap_integer(
stack[oparg(2, 0xFF)].as.uinteger (int32_t)(((uint32_t)dst_unwrap_integer(stack[oparg(2, 0xFF)]))
>> >>
stack[oparg(3, 0xFF)].as.uinteger dst_unwrap_integer(stack[oparg(3, 0xFF)]))
); );
pc++; pc++;
vm_next(); vm_next();
case DOP_SHIFT_RIGHT_UNSIGNED_IMMEDIATE: case DOP_SHIFT_RIGHT_UNSIGNED_IMMEDIATE:
stack[oparg(1, 0xFF)] = dst_wrap_integer( stack[oparg(1, 0xFF)] = dst_wrap_integer(
stack[oparg(2, 0xFF)].as.uinteger >> oparg(3, 0xFF) (int32_t) (((uint32_t)dst_unwrap_integer(stack[oparg(2, 0xFF)])) >> oparg(3, 0xFF))
); );
pc++; pc++;
vm_next(); vm_next();
@ -266,7 +266,7 @@ int dst_continue() {
case DOP_SHIFT_RIGHT_IMMEDIATE: case DOP_SHIFT_RIGHT_IMMEDIATE:
stack[oparg(1, 0xFF)] = dst_wrap_integer( stack[oparg(1, 0xFF)] = dst_wrap_integer(
(int64_t)(stack[oparg(2, 0xFF)].as.uinteger >> oparg(3, 0xFF)) (int32_t)(dst_unwrap_integer(stack[oparg(2, 0xFF)]) >> oparg(3, 0xFF))
); );
pc++; pc++;
vm_next(); vm_next();
@ -276,7 +276,7 @@ int dst_continue() {
case DOP_SHIFT_LEFT_IMMEDIATE: case DOP_SHIFT_LEFT_IMMEDIATE:
stack[oparg(1, 0xFF)] = dst_wrap_integer( stack[oparg(1, 0xFF)] = dst_wrap_integer(
stack[oparg(2, 0xFF)].as.integer << oparg(3, 0xFF) dst_unwrap_integer(stack[oparg(2, 0xFF)]) << oparg(3, 0xFF)
); );
pc++; pc++;
vm_next(); vm_next();
@ -307,43 +307,39 @@ int dst_continue() {
vm_next(); vm_next();
case DOP_LESS_THAN: case DOP_LESS_THAN:
stack[oparg(1, 0xFF)].type = DST_BOOLEAN; stack[oparg(1, 0xFF)] = dst_wrap_boolean(dst_compare(
stack[oparg(1, 0xFF)].as.boolean = dst_compare(
stack[oparg(2, 0xFF)], stack[oparg(2, 0xFF)],
stack[oparg(3, 0xFF)] stack[oparg(3, 0xFF)]
) < 0; ) < 0);
pc++; pc++;
vm_next(); vm_next();
case DOP_GREATER_THAN: case DOP_GREATER_THAN:
stack[oparg(1, 0xFF)].type = DST_BOOLEAN; stack[oparg(1, 0xFF)] = dst_wrap_boolean(dst_compare(
stack[oparg(1, 0xFF)].as.boolean = dst_compare(
stack[oparg(2, 0xFF)], stack[oparg(2, 0xFF)],
stack[oparg(3, 0xFF)] stack[oparg(3, 0xFF)]
) > 0; ) > 0);
pc++; pc++;
vm_next(); vm_next();
case DOP_EQUALS: case DOP_EQUALS:
stack[oparg(1, 0xFF)].type = DST_BOOLEAN; stack[oparg(1, 0xFF)] = dst_wrap_boolean(dst_equals(
stack[oparg(1, 0xFF)].as.boolean = dst_equals(
stack[oparg(2, 0xFF)], stack[oparg(2, 0xFF)],
stack[oparg(3, 0xFF)] stack[oparg(3, 0xFF)]
); ));
pc++; pc++;
vm_next(); vm_next();
case DOP_COMPARE: case DOP_COMPARE:
stack[oparg(1, 0xFF)].type = DST_INTEGER; stack[oparg(1, 0xFF)] = dst_wrap_integer(dst_compare(
stack[oparg(1, 0xFF)].as.integer = dst_compare( stack[oparg(2, 0xFF)],
stack[oparg(2, 0xFF)], stack[oparg(3, 0xFF)]
stack[oparg(3, 0xFF)] ));
);
pc++; pc++;
vm_next(); vm_next();
case DOP_LOAD_NIL: case DOP_LOAD_NIL:
stack[oparg(1, 0xFFFFFF)].type = DST_NIL; stack[oparg(1, 0xFFFFFF)] = dst_wrap_nil();
pc++; pc++;
vm_next(); vm_next();
@ -358,15 +354,15 @@ int dst_continue() {
vm_next(); vm_next();
case DOP_LOAD_CONSTANT: case DOP_LOAD_CONSTANT:
vm_assert(oparg(2, 0xFFFF) < func->def->constants_length, "invalid constant"); vm_assert((int32_t)oparg(2, 0xFFFF) < func->def->constants_length, "invalid constant");
stack[oparg(1, 0xFF)] = func->def->constants[oparg(2, 0xFFFF)]; stack[oparg(1, 0xFF)] = func->def->constants[(int32_t)oparg(2, 0xFFFF)];
pc++; pc++;
vm_next(); vm_next();
case DOP_LOAD_UPVALUE: case DOP_LOAD_UPVALUE:
{ {
uint32_t eindex = oparg(2, 0xFF); int32_t eindex = oparg(2, 0xFF);
uint32_t vindex = oparg(3, 0xFF); int32_t vindex = oparg(3, 0xFF);
DstFuncEnv *env; DstFuncEnv *env;
vm_assert(func->def->environments_length > eindex, "invalid upvalue"); vm_assert(func->def->environments_length > eindex, "invalid upvalue");
env = func->envs[eindex]; env = func->envs[eindex];
@ -384,8 +380,8 @@ int dst_continue() {
case DOP_SET_UPVALUE: case DOP_SET_UPVALUE:
{ {
uint32_t eindex = oparg(2, 0xFF); int32_t eindex = oparg(2, 0xFF);
uint32_t vindex = oparg(3, 0xFF); int32_t vindex = oparg(3, 0xFF);
DstFuncEnv *env; DstFuncEnv *env;
vm_assert(func->def->environments_length > eindex, "invalid upvalue"); vm_assert(func->def->environments_length > eindex, "invalid upvalue");
env = func->envs[eindex]; env = func->envs[eindex];
@ -401,12 +397,12 @@ int dst_continue() {
case DOP_CLOSURE: case DOP_CLOSURE:
{ {
uint32_t i; int32_t i;
DstFunction *fn; DstFunction *fn;
DstFuncDef *fd; DstFuncDef *fd;
vm_assert(oparg(2, 0xFFFF) < func->def->constants_length, "invalid constant"); vm_assert((int32_t)oparg(2, 0xFFFF) < func->def->constants_length, "invalid constant");
vm_assert(func->def->constants[oparg(2, 0xFFFF)].type == DST_NIL, "constant must be funcdef"); vm_assert(dst_checktype(func->def->constants[oparg(2, 0xFFFF)], DST_NIL), "constant must be funcdef");
fd = (DstFuncDef *)(func->def->constants[oparg(2, 0xFFFF)].as.pointer); fd = (DstFuncDef *)(dst_unwrap_pointer(func->def->constants[(int32_t)oparg(2, 0xFFFF)]));
fn = dst_alloc(DST_MEMORY_FUNCTION, sizeof(DstFunction)); fn = dst_alloc(DST_MEMORY_FUNCTION, sizeof(DstFunction));
fn->envs = malloc(sizeof(DstFuncEnv *) * fd->environments_length); fn->envs = malloc(sizeof(DstFuncEnv *) * fd->environments_length);
if (NULL == fn->envs) { if (NULL == fn->envs) {
@ -423,7 +419,7 @@ int dst_continue() {
fn->envs[0] = NULL; fn->envs[0] = NULL;
} }
for (i = 1; i < fd->environments_length; ++i) { for (i = 1; i < fd->environments_length; ++i) {
uint32_t inherit = fd->environments[i]; int32_t inherit = fd->environments[i];
fn->envs[i] = func->envs[inherit]; fn->envs[i] = func->envs[inherit];
} }
stack[oparg(1, 0xFF)] = dst_wrap_function(fn); stack[oparg(1, 0xFF)] = dst_wrap_function(fn);
@ -453,7 +449,7 @@ int dst_continue() {
case DOP_PUSH_ARRAY: case DOP_PUSH_ARRAY:
{ {
uint32_t count; int32_t count;
const DstValue *array; const DstValue *array;
if (dst_seq_view(stack[oparg(1, 0xFFFFFF)], &array, &count)) { if (dst_seq_view(stack[oparg(1, 0xFFFFFF)], &array, &count)) {
dst_fiber_pushn(dst_vm_fiber, array, count); dst_fiber_pushn(dst_vm_fiber, array, count);
@ -467,16 +463,16 @@ int dst_continue() {
case DOP_CALL: case DOP_CALL:
{ {
DstValue callee = stack[oparg(2, 0xFFFF)]; DstValue callee = stack[oparg(2, 0xFFFF)];
if (callee.type == DST_FUNCTION) { if (dst_checktype(callee, DST_FUNCTION)) {
func = callee.as.function; func = dst_unwrap_function(callee);
dst_fiber_funcframe(dst_vm_fiber, func); dst_fiber_funcframe(dst_vm_fiber, func);
stack = dst_vm_fiber->data + dst_vm_fiber->frame; stack = dst_vm_fiber->data + dst_vm_fiber->frame;
pc = func->def->bytecode; pc = func->def->bytecode;
vm_checkgc_next(); vm_checkgc_next();
} else if (callee.type == DST_CFUNCTION) { } else if (dst_checktype(callee, DST_CFUNCTION)) {
dst_fiber_cframe(dst_vm_fiber); dst_fiber_cframe(dst_vm_fiber);
dst_vm_fiber->ret.type = DST_NIL; dst_vm_fiber->ret = dst_wrap_nil();
if (callee.as.cfunction( if (dst_unwrap_cfunction(callee)(
dst_vm_fiber->data + dst_vm_fiber->frame, dst_vm_fiber->data + dst_vm_fiber->frame,
dst_vm_fiber->frametop - dst_vm_fiber->frame)) { dst_vm_fiber->frametop - dst_vm_fiber->frame)) {
goto vm_error; goto vm_error;
@ -489,16 +485,16 @@ int dst_continue() {
case DOP_TAILCALL: case DOP_TAILCALL:
{ {
DstValue callee = stack[oparg(2, 0xFFFF)]; DstValue callee = stack[oparg(2, 0xFFFF)];
if (callee.type == DST_FUNCTION) { if (dst_checktype(callee, DST_FUNCTION)) {
func = callee.as.function; func = dst_unwrap_function(callee);
dst_fiber_funcframe_tail(dst_vm_fiber, func); dst_fiber_funcframe_tail(dst_vm_fiber, func);
stack = dst_vm_fiber->data + dst_vm_fiber->frame; stack = dst_vm_fiber->data + dst_vm_fiber->frame;
pc = func->def->bytecode; pc = func->def->bytecode;
vm_checkgc_next(); vm_checkgc_next();
} else if (callee.type == DST_CFUNCTION) { } else if (dst_checktype(callee, DST_CFUNCTION)) {
dst_fiber_cframe_tail(dst_vm_fiber); dst_fiber_cframe_tail(dst_vm_fiber);
dst_vm_fiber->ret.type = DST_NIL; dst_vm_fiber->ret = dst_wrap_nil();
if (callee.as.cfunction( if (dst_unwrap_cfunction(callee)(
dst_vm_fiber->data + dst_vm_fiber->frame, dst_vm_fiber->data + dst_vm_fiber->frame,
dst_vm_fiber->frametop - dst_vm_fiber->frame)) { dst_vm_fiber->frametop - dst_vm_fiber->frame)) {
goto vm_error; goto vm_error;
@ -513,7 +509,7 @@ int dst_continue() {
DstCFunction f = dst_vm_syscalls[oparg(2, 0xFF)]; DstCFunction f = dst_vm_syscalls[oparg(2, 0xFF)];
vm_assert(NULL != f, "invalid syscall"); vm_assert(NULL != f, "invalid syscall");
dst_fiber_cframe(dst_vm_fiber); dst_fiber_cframe(dst_vm_fiber);
dst_vm_fiber->ret.type = DST_NIL; dst_vm_fiber->ret = dst_wrap_nil();
if (f(dst_vm_fiber->data + dst_vm_fiber->frame, if (f(dst_vm_fiber->data + dst_vm_fiber->frame,
dst_vm_fiber->frametop - dst_vm_fiber->frame)) { dst_vm_fiber->frametop - dst_vm_fiber->frame)) {
goto vm_error; goto vm_error;
@ -536,10 +532,10 @@ int dst_continue() {
DstStackFrame *frame = dst_stack_frame(stack); DstStackFrame *frame = dst_stack_frame(stack);
DstValue temp = stack[oparg(2, 0xFF)]; DstValue temp = stack[oparg(2, 0xFF)];
DstValue retvalue = stack[oparg(3, 0xFF)]; DstValue retvalue = stack[oparg(3, 0xFF)];
vm_assert(temp.type == DST_FIBER || vm_assert(dst_checktype(temp, DST_FIBER) ||
temp.type == DST_NIL, "expected fiber"); dst_checktype(temp, DST_NIL), "expected fiber");
nextfiber = temp.type == DST_FIBER nextfiber = dst_checktype(temp, DST_FIBER)
? temp.as.fiber ? dst_unwrap_fiber(temp)
: dst_vm_fiber->parent; : dst_vm_fiber->parent;
/* Check for root fiber */ /* Check for root fiber */
if (NULL == nextfiber) { if (NULL == nextfiber) {
@ -649,15 +645,15 @@ int dst_run(DstValue callee) {
} else { } else {
dst_fiber_reset(dst_vm_fiber); dst_fiber_reset(dst_vm_fiber);
} }
if (callee.type == DST_CFUNCTION) { if (dst_checktype(callee, DST_CFUNCTION)) {
dst_vm_fiber->ret = dst_wrap_nil(); dst_vm_fiber->ret = dst_wrap_nil();
dst_fiber_cframe(dst_vm_fiber); dst_fiber_cframe(dst_vm_fiber);
return callee.as.cfunction(dst_vm_fiber->data + dst_vm_fiber->frame, 0); return dst_unwrap_cfunction(callee)(dst_vm_fiber->data + dst_vm_fiber->frame, 0);
} else if (callee.type == DST_FUNCTION) { } else if (dst_checktype(callee, DST_FUNCTION)) {
dst_fiber_funcframe(dst_vm_fiber, callee.as.function); dst_fiber_funcframe(dst_vm_fiber, dst_unwrap_function(callee));
return dst_continue(); return dst_continue();
} }
dst_vm_fiber->ret = dst_wrap_string(dst_cstring("expected function")); dst_vm_fiber->ret = dst_cstringv("expected function");
return 1; return 1;
} }

View File

@ -22,6 +22,49 @@
#include <dst/dst.h> #include <dst/dst.h>
#ifdef DST_NANBOX
void *dst_nanbox_to_pointer(dst_t 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
* the high bits, and may make the pointer non-canocial on x86. */
x.i64 = (x.i64 << 16) >> 16;
return x.pointer;
}
DstValue dst_nanbox_from_pointer(void *p, uint64_t tagmask) {
DstValue ret;
ret.pointer = p;
ret.u64 &= DST_NANBOX_POINTERBITS;
ret.u64 |= tagmask;
return ret;
}
DstValue dst_nanbox_from_double(double d) {
DstValue ret;
ret.real = d;
/* Normalize NaNs */
if (d != d)
ret.u64 = dst_nanbox_tag(DST_REAL);
return ret;
}
DstValue dst_nanbox_from_bits(uint64_t bits) {
dst_t ret;
ret.u64 = bits;
return ret;
}
void dst_nanbox_memempty(DstValue *mem, uint32_t count) {
uint32_t i;
for (i = 0; i < count; i++) {
mem[i] = dst_wrap_nil();
}
}
#else
/* Wrapper functions wrap a data type that is used from C into a /* Wrapper functions wrap a data type that is used from C into a
* dst value, which can then be used in dst internal functions. Use * dst value, which can then be used in dst internal functions. Use
* these functions sparingly, as these function will let the programmer * these functions sparingly, as these function will let the programmer
@ -34,6 +77,24 @@ DstValue dst_wrap_nil() {
return y; return y;
} }
DstValue dst_wrap_true() {
DstValue y;
y.type = DST_TRUE;
return y;
}
DstValue dst_wrap_false() {
DstValue y;
y.type = DST_TRUE;
return y;
}
DstValue dst_wrap_boolean(int x) {
DstValue y;
y.type = x ? DST_TRUE : DST_FALSE;
return y;
}
#define DST_WRAP_DEFINE(NAME, TYPE, DTYPE, UM)\ #define DST_WRAP_DEFINE(NAME, TYPE, DTYPE, UM)\
DstValue dst_wrap_##NAME(TYPE x) {\ DstValue dst_wrap_##NAME(TYPE x) {\
DstValue y;\ DstValue y;\
@ -43,18 +104,19 @@ DstValue dst_wrap_##NAME(TYPE x) {\
} }
DST_WRAP_DEFINE(real, double, DST_REAL, real) DST_WRAP_DEFINE(real, double, DST_REAL, real)
DST_WRAP_DEFINE(integer, int64_t, DST_INTEGER, integer) DST_WRAP_DEFINE(integer, int32_t, DST_INTEGER, integer)
DST_WRAP_DEFINE(boolean, int, DST_BOOLEAN, boolean) DST_WRAP_DEFINE(string, const uint8_t *, DST_STRING, cpointer)
DST_WRAP_DEFINE(string, const uint8_t *, DST_STRING, string) DST_WRAP_DEFINE(symbol, const uint8_t *, DST_SYMBOL, cpointer)
DST_WRAP_DEFINE(symbol, const uint8_t *, DST_SYMBOL, string) DST_WRAP_DEFINE(array, DstArray *, DST_ARRAY, pointer)
DST_WRAP_DEFINE(array, DstArray *, DST_ARRAY, array) DST_WRAP_DEFINE(tuple, const DstValue *, DST_TUPLE, cpointer)
DST_WRAP_DEFINE(tuple, const DstValue *, DST_TUPLE, tuple) DST_WRAP_DEFINE(struct, const DstValue *, DST_STRUCT, cpointer)
DST_WRAP_DEFINE(struct, const DstValue *, DST_STRUCT, st) DST_WRAP_DEFINE(thread, DstFiber *, DST_FIBER, pointer)
DST_WRAP_DEFINE(thread, DstFiber *, DST_FIBER, fiber) DST_WRAP_DEFINE(buffer, DstBuffer *, DST_BUFFER, pointer)
DST_WRAP_DEFINE(buffer, DstBuffer *, DST_BUFFER, buffer) DST_WRAP_DEFINE(function, DstFunction *, DST_FUNCTION, pointer)
DST_WRAP_DEFINE(function, DstFunction *, DST_FUNCTION, function) DST_WRAP_DEFINE(cfunction, DstCFunction, DST_CFUNCTION, pointer)
DST_WRAP_DEFINE(cfunction, DstCFunction, DST_CFUNCTION, cfunction) DST_WRAP_DEFINE(table, DstTable *, DST_TABLE, pointer)
DST_WRAP_DEFINE(table, DstTable *, DST_TABLE, table)
DST_WRAP_DEFINE(userdata, void *, DST_USERDATA, pointer) DST_WRAP_DEFINE(userdata, void *, DST_USERDATA, pointer)
#undef DST_WRAP_DEFINE #undef DST_WRAP_DEFINE
#endif

View File

@ -20,8 +20,8 @@
* IN THE SOFTWARE. * IN THE SOFTWARE.
*/ */
#ifndef DST_H_defined #ifndef DST_NANBOX_H_defined
#define DST_H_defined #define DST_NANBOX_H_defined
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@ -33,7 +33,7 @@
* From webkit source. * From webkit source.
*/ */
/* Unix? */ /* Check Unix */
#if defined(_AIX) \ #if defined(_AIX) \
|| defined(__APPLE__) /* Darwin */ \ || defined(__APPLE__) /* Darwin */ \
|| defined(__FreeBSD__) || defined(__DragonFly__) \ || defined(__FreeBSD__) || defined(__DragonFly__) \
@ -48,12 +48,12 @@
#define DST_UNIX 1 #define DST_UNIX 1
#endif #endif
/* Windows? */ /* Check Windows */
#if defined(WIN32) || defined(_WIN32) #if defined(WIN32) || defined(_WIN32)
#define DST_WINDOWS 1 #define DST_WINDOWS 1
#endif #endif
/* 64-bit mode? */ /* Check 64-bit vs 32-bit */
#if ((defined(__x86_64__) || defined(_M_X64)) \ #if ((defined(__x86_64__) || defined(_M_X64)) \
&& (defined(DST_UNIX) || defined(DST_WINDOWS))) \ && (defined(DST_UNIX) || defined(DST_WINDOWS))) \
|| (defined(__ia64__) && defined(__LP64__)) /* Itanium in LP64 mode */ \ || (defined(__ia64__) && defined(__LP64__)) /* Itanium in LP64 mode */ \
@ -67,7 +67,7 @@
#define DST_32 1 #define DST_32 1
#endif #endif
/* Big endian? (Mostly equivallent to how WebKit does it) */ /* Check big endian */
#if defined(__MIPSEB__) /* MIPS 32-bit */ \ #if defined(__MIPSEB__) /* MIPS 32-bit */ \
|| defined(__ppc__) || defined(__PPC__) /* CPU(PPC) - PowerPC 32-bit */ \ || defined(__ppc__) || defined(__PPC__) /* CPU(PPC) - PowerPC 32-bit */ \
|| defined(__powerpc__) || defined(__powerpc) || defined(__POWERPC__) \ || defined(__powerpc__) || defined(__powerpc) || defined(__POWERPC__) \
@ -81,6 +81,8 @@
|| ((defined(__CC_ARM) || defined(__ARMCC__)) /* ARM RealView compiler */ \ || ((defined(__CC_ARM) || defined(__ARMCC__)) /* ARM RealView compiler */ \
&& defined(__BIG_ENDIAN)) && defined(__BIG_ENDIAN))
#define DST_BIG_ENDIAN 1 #define DST_BIG_ENDIAN 1
#else
#define DST_LITTLE_ENDIAN 1
#endif #endif
/* What to do when out of memory */ /* What to do when out of memory */
@ -95,46 +97,25 @@
#define DST_PLEASE_INIT do { printf("dst is uninitialized\n"); exit(1); } while (0) #define DST_PLEASE_INIT do { printf("dst is uninitialized\n"); exit(1); } while (0)
#endif #endif
#define DST_INTEGER_MIN INT64_MIN #define DST_INTEGER_MIN INT32_MIN
#define DST_INTEGER_MAX INT64_MAX #define DST_INTEGER_MAX INT32_MAX
/* Prevent some recursive functions from recursing too deeply /* Prevent some recursive functions from recursing too deeply
* ands crashing (the parser). Instead, error out. */ * ands crashing (the parser). Instead, error out. */
#define DST_RECURSION_GUARD 1000 #define DST_RECURSION_GUARD 1000
/* Names of all of the types */ #ifdef DST_NANBOX
extern const char *dst_type_names[15]; typedef union DstValue DstValue;
#else
/* Various types */
typedef enum DstType {
DST_NIL = 0,
DST_REAL,
DST_INTEGER,
DST_BOOLEAN,
DST_STRING,
DST_SYMBOL,
DST_ARRAY,
DST_TUPLE,
DST_TABLE,
DST_STRUCT,
DST_FIBER,
DST_BUFFER,
DST_FUNCTION,
DST_CFUNCTION,
DST_USERDATA
} DstType;
/* A general dst value type */
typedef struct DstValue DstValue; typedef struct DstValue DstValue;
#endif
/* All of the dst types */ /* All of the dst types */
typedef int DstBoolean;
typedef struct DstFunction DstFunction; typedef struct DstFunction DstFunction;
typedef struct DstArray DstArray; typedef struct DstArray DstArray;
typedef struct DstBuffer DstBuffer; typedef struct DstBuffer DstBuffer;
typedef struct DstTable DstTable; typedef struct DstTable DstTable;
typedef struct DstFiber DstFiber; typedef struct DstFiber DstFiber;
typedef int (*DstCFunction)(DstValue *argv, uint32_t argn);
/* Other structs */ /* Other structs */
typedef struct DstUserdataHeader DstUserdataHeader; typedef struct DstUserdataHeader DstUserdataHeader;
@ -143,42 +124,237 @@ typedef struct DstFuncEnv DstFuncEnv;
typedef struct DstStackFrame DstStackFrame; typedef struct DstStackFrame DstStackFrame;
typedef union DstValueUnion DstValueUnion; typedef union DstValueUnion DstValueUnion;
typedef struct DstUserType DstUserType; typedef struct DstUserType DstUserType;
typedef int (*DstCFunction)(DstValue *argv, int32_t argn);
/* Union datatype */ /* Names of all of the types */
union DstValueUnion { extern const char *dst_type_names[15];
DstBoolean boolean;
double real; /* Basic types for all Dst Values */
int64_t integer; typedef enum DstType {
uint64_t uinteger; DST_NIL,
DstArray *array; DST_FALSE,
DstBuffer *buffer; DST_TRUE,
DstTable *table; DST_FIBER,
DstFiber *fiber; DST_INTEGER,
const DstValue *tuple; DST_REAL,
DstCFunction cfunction; DST_STRING,
DstFunction *function; DST_SYMBOL,
const DstValue *st; DST_ARRAY,
const uint8_t *string; DST_TUPLE,
DST_TABLE,
DST_STRUCT,
DST_BUFFER,
DST_FUNCTION,
DST_CFUNCTION,
DST_USERDATA
} DstType;
/* We provide two possible implemenations of DstValues. The preferred
* nanboxing approach, and the standard C version. Code in the rest of the
* application must interact through exposed interface. */
/* Required interface for DstValue */
/* wrap and unwrap for all types */
/* Get type quickly */
/* Check against type quickly */
/* Small footprint */
/* 32 bit integer support */
/* dst_type(x)
* dst_checktype(x, t)
* dst_wrap_##TYPE(x)
* dst_unwrap_##TYPE(x)
* dst_truthy(x)
* dst_memclear(p, n) - clear memory for hash tables to nils
* dst_u64(x) - get 64 bits of payload for hashing
*/
#ifdef DST_NANBOX
union DstValue {
uint64_t u64;
int64_t i64;
void *pointer; void *pointer;
double real;
}; };
/* The general dst value type. Contains a large union and /* This representation uses 48 bit pointers. The trade off vs. the LuaJIT style
* the type information of the value */ * 47 bit payload representaion is that the type bits are no long contiguous. Type
* checking can still be fast, but typewise polymorphism takes a bit longer. However,
* hopefully we can avoid some annoying problems that occur when trying to use 47 bit pointers
* in a 48 bit address space (Linux on ARM) */
/* |.......Tag.......|.......................Payload..................| */
/* Non-double: t|11111111111|1ttt|xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */
/* Types of NIL, TRUE, and FALSE must have payload set to all 1s. */
/* Double (no NaNs): x xxxxxxxxxxx xxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */
/* A simple scheme for nan boxed values */
/* normal doubles, denormalized doubles, and infinities are doubles */
/* Quiet nan is nil. Sign bit should be 0. */
#define DST_NANBOX_TYPEBITS 0x0007000000000000lu
#define DST_NANBOX_TAGBITS 0xFFFF000000000000lu
#define DST_NANBOX_PAYLOADBITS 0x0000FFFFFFFFFFFFlu
#ifdef DST_64
#define DST_NANBOX_POINTERBITS 0x0000FFFFFFFFFFFFlu
#else
#define DST_NANBOX_POINTERBITS 0x00000000FFFFFFFFlu
#endif
#define dst_u64(x) ((x).u64)
#define dst_nanbox_lowtag(type) \
((((uint64_t)(type) & 0x8) << 12) | 0x7FF8 | (type))
#define dst_nanbox_tag(type) \
(dst_nanbox_lowtag(type) << 48)
#define dst_nanbox_checkauxtype(x, type) \
(((x).u64 & DST_NANBOX_TAGBITS) == dst_nanbox_tag((type)))
/* Check if number is nan or if number is real double */
#define dst_nanbox_isreal(x) \
(!isnan((x).real) || dst_nanbox_checkauxtype((x), DST_REAL))
#define dst_type(x) \
(isnan((x).real) \
? (((x).u64 & DST_NANBOX_TYPEBITS) >> 48) | (((x).u64 >> 60) & 0x8) \
: DST_REAL)
#define dst_checktype(x, t) \
(((t) == DST_REAL) \
? dst_nanbox_isreal(x) \
: dst_nanbox_checkauxtype((x), (t)))
void *dst_nanbox_to_pointer(DstValue x);
void dst_nanbox_memempty(DstValue *mem, int32_t count);
DstValue dst_nanbox_from_pointer(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
/* Todo - check for single mask operation */
#define dst_truthy(x) \
(!(dst_checktype((x), DST_NIL) || dst_checktype((x), DST_FALSE)))
#define dst_nanbox_from_payload(t, p) \
dst_nanbox_from_bits(dst_nanbox_tag(t) | (p))
#define dst_nanbox_wrap_(p, t) \
dst_nanbox_from_pointer((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)
#define dst_wrap_false() dst_nanbox_from_payload(DST_FALSE, 1)
#define dst_wrap_boolean(b) dst_nanbox_from_payload((b) ? DST_TRUE : DST_FALSE, 1)
#define dst_wrap_integer(i) dst_nanbox_from_payload(DST_INTEGER, (uint32_t)(i))
#define dst_wrap_real(r) dst_nanbox_from_double(r)
/* Unwrap the simple types */
#define dst_unwrap_boolean(x) \
(((x).u64 >> 48) == dst_nanbox_lowtag(DST_TRUE))
#define dst_unwrap_integer(x) \
((int32_t)((x).u64 & 0xFFFFFFFFlu))
#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_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_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)
/* Unwrap the pointer types */
#define dst_unwrap_struct(x) ((const DstValue *)dst_nanbox_to_pointer(x))
#define dst_unwrap_tuple(x) ((const DstValue *)dst_nanbox_to_pointer(x))
#define dst_unwrap_fiber(x) ((DstFiber *)dst_nanbox_to_pointer(x))
#define dst_unwrap_array(x) ((DstArray *)dst_nanbox_to_pointer(x))
#define dst_unwrap_table(x) ((DstTable *)dst_nanbox_to_pointer(x))
#define dst_unwrap_buffer(x) ((DstBuffer *)dst_nanbox_to_pointer(x))
#define dst_unwrap_string(x) ((const uint8_t *)dst_nanbox_to_pointer(x))
#define dst_unwrap_symbol(x) ((const uint8_t *)dst_nanbox_to_pointer(x))
#define dst_unwrap_userdata(x) (dst_nanbox_to_pointer(x))
#define dst_unwrap_pointer(x) (dst_nanbox_to_pointer(x))
#define dst_unwrap_function(x) ((DstFunction *)dst_nanbox_to_pointer(x))
#define dst_unwrap_cfunction(x) ((DstCFunction)dst_nanbox_to_pointer(x))
/* End of [#ifdef DST_NANBOX] */
#else
/* A general dst value type */
struct DstValue { struct DstValue {
DstValueUnion as; union {
uint64_t u64;
double real;
int32_t integer;
void *pointer;
const void *cpointer;
} as;
DstType type; DstType type;
}; };
#define dst_u64(x) ((x).as.u64)
#define dst_memempty(mem, count) memset((mem), 0, sizeof(DstValue) * (count))
#define dst_type(x) ((x).type)
#define dst_checktype(x, t) ((x).type == (t))
#define dst_truthy(x) \
((x).type != DST_NIL && (x).type != DST_FALSE)
#define dst_unwrap_struct(x) ((const DstValue *)(x).as.pointer)
#define dst_unwrap_tuple(x) ((const DstValue *)(x).as.pointer)
#define dst_unwrap_fiber(x) ((DstFiber *)(x).as.pointer)
#define dst_unwrap_array(x) ((DstArray *)(x).as.pointer)
#define dst_unwrap_table(x) ((DstTable *)(x).as.pointer)
#define dst_unwrap_buffer(x) ((DstBuffer *)(x).as.pointer)
#define dst_unwrap_string(x) ((const uint8_t *)(x).as.pointer)
#define dst_unwrap_symbol(x) ((const uint8_t *)(x).as.pointer)
#define dst_unwrap_userdata(x) ((x).as.pointer)
#define dst_unwrap_pointer(x) ((x).as.pointer)
#define dst_unwrap_function(x) ((DstFunction *)(x).as.pointer)
#define dst_unwrap_cfunction(x) ((DstCFunction)(x).as.pointer)
#define dst_unwrap_boolean(x) ((x).type == DST_TRUE)
#define dst_unwrap_integer(x) ((x).as.integer)
#define dst_unwrap_real(x) ((x).as.real)
DstValue dst_wrap_nil();
DstValue dst_wrap_real(double x);
DstValue dst_wrap_integer(int32_t x);
DstValue dst_wrap_true();
DstValue dst_wrap_false();
DstValue dst_wrap_boolean(int x);
DstValue dst_wrap_string(const uint8_t *x);
DstValue dst_wrap_symbol(const uint8_t *x);
DstValue dst_wrap_array(DstArray *x);
DstValue dst_wrap_tuple(const DstValue *x);
DstValue dst_wrap_struct(const DstValue *x);
DstValue dst_wrap_fiber(DstFiber *x);
DstValue dst_wrap_buffer(DstBuffer *x);
DstValue dst_wrap_function(DstFunction *x);
DstValue dst_wrap_cfunction(DstCFunction x);
DstValue dst_wrap_table(DstTable *x);
DstValue dst_wrap_userdata(void *x);
/* End of tagged union implementation */
#endif
/* A lightweight green thread in dst. Does not correspond to /* A lightweight green thread in dst. Does not correspond to
* operating system threads. */ * operating system threads. */
struct DstFiber { struct DstFiber {
DstValue ret; /* Return value */ DstValue ret; /* Return value */
DstValue *data; DstValue *data;
DstFiber *parent; DstFiber *parent;
uint32_t frame; /* Index of the stack frame */ int32_t frame; /* Index of the stack frame */
uint32_t frametop; /* Index of top of stack frame */ int32_t frametop; /* Index of top of stack frame */
uint32_t stacktop; /* Top of stack. Where values are pushed and popped from. */ int32_t stacktop; /* Top of stack. Where values are pushed and popped from. */
uint32_t capacity; int32_t capacity;
enum { enum {
DST_FIBER_PENDING = 0, DST_FIBER_PENDING = 0,
DST_FIBER_ALIVE, DST_FIBER_ALIVE,
@ -191,7 +367,7 @@ struct DstFiber {
struct DstStackFrame { struct DstStackFrame {
DstFunction *func; DstFunction *func;
uint32_t *pc; uint32_t *pc;
uint32_t prevframe; int32_t prevframe;
}; };
/* Number of DstValues a frame takes up in the stack */ /* Number of DstValues a frame takes up in the stack */
@ -200,23 +376,23 @@ struct DstStackFrame {
/* A dynamic array type. */ /* A dynamic array type. */
struct DstArray { struct DstArray {
DstValue *data; DstValue *data;
uint32_t count; int32_t count;
uint32_t capacity; int32_t capacity;
}; };
/* A bytebuffer type. Used as a mutable string or string builder. */ /* A bytebuffer type. Used as a mutable string or string builder. */
struct DstBuffer { struct DstBuffer {
uint8_t *data; uint8_t *data;
uint32_t count; int32_t count;
uint32_t capacity; int32_t capacity;
}; };
/* A mutable associative data type. Backed by a hashtable. */ /* A mutable associative data type. Backed by a hashtable. */
struct DstTable { struct DstTable {
DstValue *data; DstValue *data;
uint32_t count; int32_t count;
uint32_t capacity; int32_t capacity;
uint32_t deleted; int32_t deleted;
}; };
/* Some function defintion flags */ /* Some function defintion flags */
@ -225,16 +401,16 @@ struct DstTable {
/* A function definition. Contains information needed to instantiate closures. */ /* A function definition. Contains information needed to instantiate closures. */
struct DstFuncDef { struct DstFuncDef {
uint32_t *environments; /* Which environments to capture from parent. */ int32_t *environments; /* Which environments to capture from parent. */
DstValue *constants; /* Contains strings, FuncDefs, etc. */ DstValue *constants; /* Contains strings, FuncDefs, etc. */
uint32_t *bytecode; uint32_t *bytecode;
uint32_t flags; uint32_t flags;
uint32_t slotcount; /* The amount of stack space required for the function */ int32_t slotcount; /* The amount of stack space required for the function */
uint32_t arity; /* Not including varargs */ int32_t arity; /* Not including varargs */
uint32_t constants_length; int32_t constants_length;
uint32_t bytecode_length; int32_t bytecode_length;
uint32_t environments_length; int32_t environments_length;
}; };
/* A fuction environment */ /* A fuction environment */
@ -243,8 +419,8 @@ struct DstFuncEnv {
DstFiber *fiber; DstFiber *fiber;
DstValue *values; DstValue *values;
} as; } as;
uint32_t length; /* Size of environment */ int32_t length; /* Size of environment */
uint32_t offset; /* Stack offset when values still on stack. If offset is 0, then int32_t offset; /* Stack offset when values still on stack. If offset is 0, then
environment is no longer on the stack. */ environment is no longer on the stack. */
}; };
@ -258,15 +434,15 @@ struct DstFunction {
/* Defines a type for userdata */ /* Defines a type for userdata */
struct DstUserType { struct DstUserType {
const char *name; const char *name;
int (*serialize)(void *data, uint32_t len); int (*serialize)(void *data, size_t len);
int (*deserialize)(); int (*deserialize)();
void (*finalize)(void *data, uint32_t len); void (*finalize)(void *data, size_t len);
}; };
/* Contains information about userdata */ /* Contains information about userdata */
struct DstUserdataHeader { struct DstUserdataHeader {
const DstUserType *type; const DstUserType *type;
uint32_t size; size_t size;
}; };
/* The VM state. Rather than a struct that is passed /* The VM state. Rather than a struct that is passed
@ -294,22 +470,22 @@ extern const DstCFunction dst_vm_syscalls[256];
extern DstFiber *dst_vm_fiber; extern DstFiber *dst_vm_fiber;
/* Array functions */ /* Array functions */
DstArray *dst_array(uint32_t capacity); DstArray *dst_array(int32_t capacity);
DstArray *dst_array_init(DstArray *array, uint32_t capacity); DstArray *dst_array_init(DstArray *array, int32_t capacity);
void dst_array_deinit(DstArray *array); void dst_array_deinit(DstArray *array);
void dst_array_ensure(DstArray *array, uint32_t capacity); void dst_array_ensure(DstArray *array, int32_t capacity);
void dst_array_setcount(DstArray *array, uint32_t count); void dst_array_setcount(DstArray *array, int32_t count);
void dst_array_push(DstArray *array, DstValue x); void dst_array_push(DstArray *array, DstValue x);
DstValue dst_array_pop(DstArray *array); DstValue dst_array_pop(DstArray *array);
DstValue dst_array_peek(DstArray *array); DstValue dst_array_peek(DstArray *array);
/* Buffer functions */ /* Buffer functions */
DstBuffer *dst_buffer(uint32_t capacity); DstBuffer *dst_buffer(int32_t capacity);
DstBuffer *dst_buffer_init(DstBuffer *buffer, uint32_t capacity); DstBuffer *dst_buffer_init(DstBuffer *buffer, int32_t capacity);
void dst_buffer_deinit(DstBuffer *buffer); void dst_buffer_deinit(DstBuffer *buffer);
void dst_buffer_ensure(DstBuffer *buffer, uint32_t capacity); void dst_buffer_ensure(DstBuffer *buffer, int32_t capacity);
void dst_buffer_extra(DstBuffer *buffer, uint32_t n); void dst_buffer_extra(DstBuffer *buffer, int32_t n);
void dst_buffer_push_bytes(DstBuffer *buffer, const uint8_t *string, uint32_t len); void dst_buffer_push_bytes(DstBuffer *buffer, const uint8_t *string, int32_t len);
void dst_buffer_push_cstring(DstBuffer *buffer, const char *cstring); void dst_buffer_push_cstring(DstBuffer *buffer, const char *cstring);
void dst_buffer_push_u8(DstBuffer *buffer, uint8_t x); void dst_buffer_push_u8(DstBuffer *buffer, uint8_t x);
void dst_buffer_push_u16(DstBuffer *buffer, uint16_t x); void dst_buffer_push_u16(DstBuffer *buffer, uint16_t x);
@ -317,27 +493,27 @@ void dst_buffer_push_u32(DstBuffer *buffer, uint32_t x);
void dst_buffer_push_u64(DstBuffer *buffer, uint64_t x); void dst_buffer_push_u64(DstBuffer *buffer, uint64_t x);
/* Tuple */ /* Tuple */
#define dst_tuple_raw(t) ((uint32_t *)(t) - 2) #define dst_tuple_raw(t) ((int32_t *)(t) - 2)
#define dst_tuple_length(t) (dst_tuple_raw(t)[0]) #define dst_tuple_length(t) (dst_tuple_raw(t)[0])
#define dst_tuple_hash(t) (dst_tuple_raw(t)[1]) #define dst_tuple_hash(t) ((dst_tuple_raw(t)[1]))
DstValue *dst_tuple_begin(uint32_t length); DstValue *dst_tuple_begin(int32_t length);
const DstValue *dst_tuple_end(DstValue *tuple); const DstValue *dst_tuple_end(DstValue *tuple);
const DstValue *dst_tuple_n(DstValue *values, uint32_t n); const DstValue *dst_tuple_n(DstValue *values, int32_t n);
int dst_tuple_equal(const DstValue *lhs, const DstValue *rhs); int dst_tuple_equal(const DstValue *lhs, const DstValue *rhs);
int dst_tuple_compare(const DstValue *lhs, const DstValue *rhs); int dst_tuple_compare(const DstValue *lhs, const DstValue *rhs);
/* String/Symbol functions */ /* String/Symbol functions */
#define dst_string_raw(s) ((uint32_t *)(s) - 2) #define dst_string_raw(s) ((int32_t *)(s) - 2)
#define dst_string_length(s) (dst_string_raw(s)[0]) #define dst_string_length(s) (dst_string_raw(s)[0])
#define dst_string_hash(s) (dst_string_raw(s)[1]) #define dst_string_hash(s) ((dst_string_raw(s)[1]))
uint8_t *dst_string_begin(uint32_t length); uint8_t *dst_string_begin(int32_t length);
const uint8_t *dst_string_end(uint8_t *str); const uint8_t *dst_string_end(uint8_t *str);
const uint8_t *dst_string(const uint8_t *buf, uint32_t len); const uint8_t *dst_string(const uint8_t *buf, int32_t len);
const uint8_t *dst_cstring(const char *cstring); const uint8_t *dst_cstring(const char *cstring);
int dst_string_compare(const uint8_t *lhs, const uint8_t *rhs); int dst_string_compare(const uint8_t *lhs, const uint8_t *rhs);
int dst_string_equal(const uint8_t *lhs, const uint8_t *rhs); int dst_string_equal(const uint8_t *lhs, const uint8_t *rhs);
int dst_string_equalconst(const uint8_t *lhs, const uint8_t *rhs, uint32_t rlen, uint32_t rhash); int dst_string_equalconst(const uint8_t *lhs, const uint8_t *rhs, int32_t rlen, int32_t rhash);
const uint8_t *dst_string_unique(const uint8_t *buf, uint32_t len); const uint8_t *dst_string_unique(const uint8_t *buf, int32_t len);
const uint8_t *dst_cstring_unique(const char *s); const uint8_t *dst_cstring_unique(const char *s);
const uint8_t *dst_description(DstValue x); const uint8_t *dst_description(DstValue x);
const uint8_t *dst_to_string(DstValue x); const uint8_t *dst_to_string(DstValue x);
@ -346,19 +522,19 @@ const uint8_t *dst_formatc(const char *format, ...);
void dst_puts(const uint8_t *str); void dst_puts(const uint8_t *str);
/* Symbol functions */ /* Symbol functions */
const uint8_t *dst_symbol(const uint8_t *str, uint32_t len); const uint8_t *dst_symbol(const uint8_t *str, int32_t len);
const uint8_t *dst_symbol_from_string(const uint8_t *str); const uint8_t *dst_symbol_from_string(const uint8_t *str);
const uint8_t *dst_csymbol(const char *str); const uint8_t *dst_csymbol(const char *str);
const uint8_t *dst_symbol_gen(const uint8_t *buf, uint32_t len); const uint8_t *dst_symbol_gen(const uint8_t *buf, int32_t len);
#define dst_symbolv(str, len) dst_wrap_symbol(dst_symbol((str), (len))) #define dst_symbolv(str, len) dst_wrap_symbol(dst_symbol((str), (len)))
#define dst_csymbolv(cstr) dst_wrap_symbol(dst_csymbol(cstr)) #define dst_csymbolv(cstr) dst_wrap_symbol(dst_csymbol(cstr))
/* Structs */ /* Structs */
#define dst_struct_raw(t) ((uint32_t *)(t) - 2) #define dst_struct_raw(t) ((int32_t *)(t) - 2)
#define dst_struct_length(t) (dst_struct_raw(t)[0]) #define dst_struct_length(t) (dst_struct_raw(t)[0])
#define dst_struct_capacity(t) (dst_struct_length(t) * 4) #define dst_struct_capacity(t) (dst_struct_length(t) * 4)
#define dst_struct_hash(t) (dst_struct_raw(t)[1]) #define dst_struct_hash(t) ((dst_struct_raw(t)[1]))
DstValue *dst_struct_begin(uint32_t count); DstValue *dst_struct_begin(int32_t count);
void dst_struct_put(DstValue *st, DstValue key, DstValue value); void dst_struct_put(DstValue *st, DstValue key, DstValue value);
const DstValue *dst_struct_end(DstValue *st); const DstValue *dst_struct_end(DstValue *st);
DstValue dst_struct_get(const DstValue *st, DstValue key); DstValue dst_struct_get(const DstValue *st, DstValue key);
@ -368,8 +544,8 @@ int dst_struct_equal(const DstValue *lhs, const DstValue *rhs);
int dst_struct_compare(const DstValue *lhs, const DstValue *rhs); int dst_struct_compare(const DstValue *lhs, const DstValue *rhs);
/* Table functions */ /* Table functions */
DstTable *dst_table(uint32_t capacity); DstTable *dst_table(int32_t capacity);
DstTable *dst_table_init(DstTable *table, uint32_t capacity); DstTable *dst_table_init(DstTable *table, int32_t capacity);
void dst_table_deinit(DstTable *table); void dst_table_deinit(DstTable *table);
DstValue dst_table_get(DstTable *t, DstValue key); DstValue dst_table_get(DstTable *t, DstValue key);
DstValue dst_table_remove(DstTable *t, DstValue key); DstValue dst_table_remove(DstTable *t, DstValue key);
@ -378,15 +554,15 @@ DstValue dst_table_next(DstTable *t, DstValue key);
const DstValue *dst_table_to_struct(DstTable *t); const DstValue *dst_table_to_struct(DstTable *t);
/* Fiber */ /* Fiber */
DstFiber *dst_fiber(uint32_t capacity); DstFiber *dst_fiber(int32_t capacity);
#define dst_stack_frame(s) ((DstStackFrame *)((s) - DST_FRAME_SIZE)) #define dst_stack_frame(s) ((DstStackFrame *)((s) - DST_FRAME_SIZE))
#define dst_fiber_frame(f) dst_stack_frame((f)->data + (f)->frame) #define dst_fiber_frame(f) dst_stack_frame((f)->data + (f)->frame)
DstFiber *dst_fiber_reset(DstFiber *fiber); DstFiber *dst_fiber_reset(DstFiber *fiber);
void dst_fiber_setcapacity(DstFiber *fiber, uint32_t n); void dst_fiber_setcapacity(DstFiber *fiber, int32_t n);
void dst_fiber_push(DstFiber *fiber, DstValue x); void dst_fiber_push(DstFiber *fiber, DstValue x);
void dst_fiber_push2(DstFiber *fiber, DstValue x, DstValue y); void dst_fiber_push2(DstFiber *fiber, DstValue x, DstValue y);
void dst_fiber_push3(DstFiber *fiber, DstValue x, DstValue y, DstValue z); void dst_fiber_push3(DstFiber *fiber, DstValue x, DstValue y, DstValue z);
void dst_fiber_pushn(DstFiber *fiber, const DstValue *arr, uint32_t n); void dst_fiber_pushn(DstFiber *fiber, const DstValue *arr, int32_t n);
DstValue dst_fiber_popvalue(DstFiber *fiber); DstValue dst_fiber_popvalue(DstFiber *fiber);
void dst_fiber_funcframe(DstFiber *fiber, DstFunction *func); void dst_fiber_funcframe(DstFiber *fiber, DstFunction *func);
void dst_fiber_funcframe_tail(DstFiber *fiber, DstFunction *func); void dst_fiber_funcframe_tail(DstFiber *fiber, DstFunction *func);
@ -420,9 +596,9 @@ DstAssembleResult dst_asm(DstAssembleOptions opts);
DstFunction *dst_asm_func(DstAssembleResult result); DstFunction *dst_asm_func(DstAssembleResult result);
/* Treat similar types through uniform interfaces for iteration */ /* Treat similar types through uniform interfaces for iteration */
int dst_seq_view(DstValue seq, const DstValue **data, uint32_t *len); int dst_seq_view(DstValue seq, const DstValue **data, int32_t *len);
int dst_chararray_view(DstValue str, const uint8_t **data, uint32_t *len); int dst_chararray_view(DstValue str, const uint8_t **data, int32_t *len);
int dst_hashtable_view(DstValue tab, const DstValue **data, uint32_t *len, uint32_t *cap); int dst_hashtable_view(DstValue tab, const DstValue **data, int32_t *len, int32_t *cap);
/* Userdata */ /* Userdata */
#define dst_userdata_header(u) ((DstUserdataHeader *)(u) - 1) #define dst_userdata_header(u) ((DstUserdataHeader *)(u) - 1)
@ -430,25 +606,21 @@ int dst_hashtable_view(DstValue tab, const DstValue **data, uint32_t *len, uint3
#define dst_userdata_size(u) (dst_userdata_header(u)->size) #define dst_userdata_size(u) (dst_userdata_header(u)->size)
/* Value functions */ /* Value functions */
int dst_truthy(DstValue v);
int dst_equals(DstValue x, DstValue y); int dst_equals(DstValue x, DstValue y);
uint32_t dst_hash(DstValue x); int32_t dst_hash(DstValue x);
int dst_compare(DstValue x, DstValue y); int dst_compare(DstValue x, DstValue y);
uint32_t dst_calchash_array(const DstValue *array, uint32_t len);
DstValue dst_get(DstValue ds, DstValue key); DstValue dst_get(DstValue ds, DstValue key);
void dst_put(DstValue ds, DstValue key, DstValue value); void dst_put(DstValue ds, DstValue key, DstValue value);
DstValue dst_next(DstValue ds, DstValue key); DstValue dst_next(DstValue ds, DstValue key);
uint32_t dst_length(DstValue x); int32_t dst_length(DstValue x);
uint32_t dst_capacity(DstValue x); int32_t dst_capacity(DstValue x);
DstValue dst_getindex(DstValue ds, uint32_t index); DstValue dst_getindex(DstValue ds, int32_t index);
void dst_setindex(DstValue ds, DstValue value, uint32_t index); void dst_setindex(DstValue ds, DstValue value, int32_t index);
/* Utils */ /* Utils */
extern const char dst_base64[65]; extern const char dst_base64[65];
int64_t dst_real_to_integer(double real); int32_t dst_array_calchash(const DstValue *array, int32_t len);
double dst_integer_to_real(int64_t integer); int32_t dst_string_calchash(const uint8_t *str, int32_t len);
uint32_t dst_array_calchash(const DstValue *array, uint32_t len);
uint32_t dst_string_calchash(const uint8_t *str, uint32_t len);
/* Parsing */ /* Parsing */
typedef enum { typedef enum {
@ -463,10 +635,10 @@ struct DstParseResult {
const uint8_t *error; const uint8_t *error;
} result; } result;
DstValue map; DstValue map;
uint32_t bytes_read; int32_t bytes_read;
DstParseStatus status; DstParseStatus status;
}; };
DstParseResult dst_parse(const uint8_t *src, uint32_t len); DstParseResult dst_parse(const uint8_t *src, int32_t len);
DstParseResult dst_parsec(const char *src); DstParseResult dst_parsec(const char *src);
/* VM functions */ /* VM functions */
@ -477,21 +649,7 @@ int dst_run(DstValue callee);
DstValue dst_transfer(DstFiber *fiber, DstValue x); DstValue dst_transfer(DstFiber *fiber, DstValue x);
/* Wrap data in DstValue */ /* Wrap data in DstValue */
DstValue dst_wrap_nil();
DstValue dst_wrap_real(double x);
DstValue dst_wrap_integer(int64_t x);
DstValue dst_wrap_boolean(int x);
DstValue dst_wrap_string(const uint8_t *x);
DstValue dst_wrap_symbol(const uint8_t *x);
DstValue dst_wrap_array(DstArray *x);
DstValue dst_wrap_tuple(const DstValue *x);
DstValue dst_wrap_struct(const DstValue *x);
DstValue dst_wrap_fiber(DstFiber *x);
DstValue dst_wrap_buffer(DstBuffer *x);
DstValue dst_wrap_function(DstFunction *x);
DstValue dst_wrap_cfunction(DstCFunction x);
DstValue dst_wrap_table(DstTable *x);
DstValue dst_wrap_userdata(void *x);
/* GC */ /* GC */

View File

@ -35,25 +35,6 @@ union dst_t {
* hopefully we can avoid some annoying problems that occur when trying to use 47 bit pointers * hopefully we can avoid some annoying problems that occur when trying to use 47 bit pointers
* in a 48 bit address space (Linux on ARM) */ * in a 48 bit address space (Linux on ARM) */
enum dst_t_tag {
DST_T_NIL,
DST_T_TRUE,
DST_T_FALSE,
DST_T_INTEGER,
DST_T_FIBER,
DST_T_STRUCT,
DST_T_TUPLE,
DST_T_ARRAY,
DST_T_BUFFER,
DST_T_TABLE,
DST_T_USERDATA,
DST_T_FUNCTION,
DST_T_CFUNCTION,
DST_T_STRING,
DST_T_SYMBOL,
DST_T_REAL
};
/* |.......Tag.......|.......................Payload..................| */ /* |.......Tag.......|.......................Payload..................| */
/* Non-double: t|11111111111|1ttt|xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ /* Non-double: t|11111111111|1ttt|xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */
/* Types of NIL, TRUE, and FALSE must have payload set to all 1s. */ /* Types of NIL, TRUE, and FALSE must have payload set to all 1s. */
@ -65,6 +46,7 @@ enum dst_t_tag {
/* Quiet nan is nil. Sign bit should be 0. */ /* Quiet nan is nil. Sign bit should be 0. */
#define DST_NANBOX_TYPEBITS 0x0007000000000000lu #define DST_NANBOX_TYPEBITS 0x0007000000000000lu
#define DST_NANBOX_TAGBITS 0xFFFF000000000000lu
#ifdef DST_64 #ifdef DST_64
#define DST_NANBOX_POINTERBITS 0x0000FFFFFFFFFFFFlu #define DST_NANBOX_POINTERBITS 0x0000FFFFFFFFFFFFlu
@ -74,11 +56,16 @@ enum dst_t_tag {
#define DST_NANBOX_QUIET_BIT 0x0008000000000000lu #define DST_NANBOX_QUIET_BIT 0x0008000000000000lu
#define dst_nanbox_isreal(x) (!isnan((x).real))
#define dst_nanbox_tag(type) \ #define dst_nanbox_tag(type) \
((((uint64_t)(type) & 0x8) << 12) | 0x7FF8 | (type)) ((((uint64_t)(type) & 0x8) << 12) | 0x7FF8 | (type))
#define dst_nanbox_checkauxtype(x, type) \
(((x).u64 & DST_NANBOX_TAGBITS) == (dst_nanbox_tag((type)) << 48))
/* Check if number is nan or if number is real double */
#define dst_nanbox_isreal(x) \
(!isnan((x).real) || dst_nanbox_checkauxtype((x), DST_REAL))
#define dst_nanbox_tagbits(x) \ #define dst_nanbox_tagbits(x) \
((x).u64 & 0xFFFF000000000000lu) ((x).u64 & 0xFFFF000000000000lu)
@ -86,14 +73,14 @@ enum dst_t_tag {
((x).u64 & 0x0000FFFFFFFFFFFFlu) ((x).u64 & 0x0000FFFFFFFFFFFFlu)
#define dst_nanbox_type(x) \ #define dst_nanbox_type(x) \
(dst_nanbox_isreal(x) \ (isnan((x).real) \
? DST_T_REAL \ ? (((x).u64 & DST_NANBOX_TYPEBITS) >> 48) | (((x).u64 >> 60) & 0x8) \
: (((x).u64 & DST_NANBOX_TYPEBITS) >> 48) | (((x).u64 >> 60) & 0x8)) : DST_REAL)
#define dst_nanbox_checktype(x, t) \ #define dst_nanbox_checktype(x, t) \
(((t) == DST_T_REAL) \ (((t) == DST_REAL) \
? dst_nanbox_isreal(x) \ ? dst_nanbox_isreal(x) \
: (!dst_nanbox_isreal(x) && (((x).u64 >> 48) == dst_nanbox_tag(t)))) : dst_nanbox_checkauxtype((x), (t)))
static inline void *dst_nanbox_to_pointer(dst_t x) { static inline void *dst_nanbox_to_pointer(dst_t x) {
/* We need to do this shift to keep the higher bits of the pointer /* We need to do this shift to keep the higher bits of the pointer
@ -115,9 +102,9 @@ static inline dst_t dst_nanbox_from_pointer(void *p, uint64_t tagmask) {
static inline dst_t dst_nanbox_from_double(double d) { static inline dst_t dst_nanbox_from_double(double d) {
dst_t ret; dst_t ret;
ret.real = d; ret.real = d;
/* Normalize NaNs to nil */ /* Normalize NaNs */
if (d != d) if (d != d)
ret.u64 = dst_nanbox_tag(DST_T_NIL) << 48; ret.u64 = dst_nanbox_tag(DST_REAL) << 48;
return ret; return ret;
} }
@ -137,15 +124,15 @@ static inline dst_t dst_nanbox_from_bits(uint64_t bits) {
dst_nanbox_from_pointer((p), (dst_nanbox_tag(t) << 48) | 0x7FF8000000000000lu) dst_nanbox_from_pointer((p), (dst_nanbox_tag(t) << 48) | 0x7FF8000000000000lu)
/* Wrap the simple types */ /* Wrap the simple types */
#define dst_nanbox_wrap_nil() dst_nanbox_from_payload(DST_T_NIL, 0xFFFFFFFFFFFFlu) #define dst_nanbox_wrap_nil() dst_nanbox_from_payload(DST_NIL, 1)
#define dst_nanbox_wrap_true() dst_nanbox_from_payload(DST_T_TRUE, 0xFFFFFFFFFFFFlu) #define dst_nanbox_wrap_true() dst_nanbox_from_payload(DST_TRUE, 1)
#define dst_nanbox_wrap_false() dst_nanbox_from_payload(DST_T_FALSE, 0xFFFFFFFFFFFFlu) #define dst_nanbox_wrap_false() dst_nanbox_from_payload(DST_FALSE, 1)
#define dst_nanbox_wrap_boolean(b) dst_nanbox_from_payload((b) ? DST_T_TRUE : DST_T_FALSE, 0xFFFFFFFFFFFFlu) #define dst_nanbox_wrap_boolean(b) dst_nanbox_from_payload((b) ? DST_TRUE : DST_FALSE, 1)
#define dst_nanbox_wrap_integer(i) dst_nanbox_from_payload(DST_T_INTEGER, (uint32_t)(i)) #define dst_nanbox_wrap_integer(i) dst_nanbox_from_payload(DST_INTEGER, (uint32_t)(i))
#define dst_nanbox_wrap_real(r) dst_nanbox_from_double(r) #define dst_nanbox_wrap_real(r) dst_nanbox_from_double(r)
#define dst_nanbox_unwrap_boolean(x) \ #define dst_nanbox_unwrap_boolean(x) \
(((x).u64 >> 48) == dst_nanbox_tag(DST_T_TRUE)) (((x).u64 >> 48) == dst_nanbox_tag(DST_TRUE))
#define dst_nanbox_unwrap_integer(x) \ #define dst_nanbox_unwrap_integer(x) \
((int32_t)((x).u64 & 0xFFFFFFFFlu)) ((int32_t)((x).u64 & 0xFFFFFFFFlu))
@ -153,17 +140,17 @@ static inline dst_t dst_nanbox_from_bits(uint64_t bits) {
#define dst_nanbox_unwrap_real(x) ((x).real) #define dst_nanbox_unwrap_real(x) ((x).real)
/* Wrap the pointer types */ /* Wrap the pointer types */
#define dst_nanbox_wrap_struct(s) dst_nanbox_wrap_((s), DST_T_STRUCT) #define dst_nanbox_wrap_struct(s) dst_nanbox_wrap_((s), DST_STRUCT)
#define dst_nanbox_wrap_tuple(s) dst_nanbox_wrap_((s), DST_T_TUPLE) #define dst_nanbox_wrap_tuple(s) dst_nanbox_wrap_((s), DST_TUPLE)
#define dst_nanbox_wrap_fiber(s) dst_nanbox_wrap_((s), DST_T_FIBER) #define dst_nanbox_wrap_fiber(s) dst_nanbox_wrap_((s), DST_FIBER)
#define dst_nanbox_wrap_array(s) dst_nanbox_wrap_((s), DST_T_ARRAY) #define dst_nanbox_wrap_array(s) dst_nanbox_wrap_((s), DST_ARRAY)
#define dst_nanbox_wrap_table(s) dst_nanbox_wrap_((s), DST_T_TABLE) #define dst_nanbox_wrap_table(s) dst_nanbox_wrap_((s), DST_TABLE)
#define dst_nanbox_wrap_buffer(s) dst_nanbox_wrap_((s), DST_T_BUFFER) #define dst_nanbox_wrap_buffer(s) dst_nanbox_wrap_((s), DST_BUFFER)
#define dst_nanbox_wrap_string(s) dst_nanbox_wrap_((s), DST_T_STRING) #define dst_nanbox_wrap_string(s) dst_nanbox_wrap_((s), DST_STRING)
#define dst_nanbox_wrap_symbol(s) dst_nanbox_wrap_((s), DST_T_SYMBOL) #define dst_nanbox_wrap_symbol(s) dst_nanbox_wrap_((s), DST_SYMBOL)
#define dst_nanbox_wrap_userdata(s) dst_nanbox_wrap_((s), DST_T_USERDATA) #define dst_nanbox_wrap_userdata(s) dst_nanbox_wrap_((s), DST_USERDATA)
#define dst_nanbox_wrap_function(s) dst_nanbox_wrap_((s), DST_T_FUNCTION) #define dst_nanbox_wrap_function(s) dst_nanbox_wrap_((s), DST_FUNCTION)
#define dst_nanbox_wrap_cfunction(s) dst_nanbox_wrap_((s), DST_T_CFUNCTION) #define dst_nanbox_wrap_cfunction(s) dst_nanbox_wrap_((s), DST_CFUNCTION)
/* Unwrap the pointer types */ /* Unwrap the pointer types */
#define dst_nanbox_unwrap_struct(x) ((const DstValue *)dst_nanbox_to_pointer(x)) #define dst_nanbox_unwrap_struct(x) ((const DstValue *)dst_nanbox_to_pointer(x))
@ -179,61 +166,61 @@ static inline dst_t dst_nanbox_from_bits(uint64_t bits) {
#define dst_nanbox_unwrap_cfunction(x) ((DstCFunction)dst_nanbox_to_pointer(x)) #define dst_nanbox_unwrap_cfunction(x) ((DstCFunction)dst_nanbox_to_pointer(x))
void dst_nanbox_print(dst_t x) { void dst_nanbox_print(dst_t x) {
assert(dst_nanbox_checktype(x, dst_nanbox_type(x)));
printf("hex: 0x%lx, " printf("hex: 0x%lx, "
"description: ", x.u64); "description: ", x.u64);
switch (dst_nanbox_type(x)) { switch (dst_nanbox_type(x)) {
case DST_T_NIL: case DST_NIL:
printf("nil\n"); printf("nil\n");
break; break;
case DST_T_TRUE: case DST_TRUE:
printf("true\n"); printf("true\n");
break; break;
case DST_T_FALSE: case DST_FALSE:
printf("false\n"); printf("false\n");
break; break;
case DST_T_INTEGER: case DST_INTEGER:
printf("%dI\n", dst_nanbox_unwrap_integer(x)); printf("%dI\n", dst_nanbox_unwrap_integer(x));
break; break;
case DST_T_STRUCT: case DST_STRUCT:
printf("<struct %p>\n", dst_nanbox_unwrap_struct(x)); printf("<struct %p>\n", dst_nanbox_unwrap_struct(x));
break; break;
case DST_T_TUPLE: case DST_TUPLE:
printf("<tuple %p>\n", dst_nanbox_unwrap_tuple(x)); printf("<tuple %p>\n", dst_nanbox_unwrap_tuple(x));
break; break;
case DST_T_FIBER: case DST_FIBER:
printf("<fiber %p>\n", dst_nanbox_unwrap_fiber(x)); printf("<fiber %p>\n", dst_nanbox_unwrap_fiber(x));
break; break;
case DST_T_ARRAY: case DST_ARRAY:
printf("<array %p>\n", dst_nanbox_unwrap_array(x)); printf("<array %p>\n", dst_nanbox_unwrap_array(x));
break; break;
case DST_T_TABLE: case DST_TABLE:
printf("<table %p>\n", dst_nanbox_unwrap_table(x)); printf("<table %p>\n", dst_nanbox_unwrap_table(x));
break; break;
case DST_T_STRING: case DST_STRING:
printf("<string %p>\n", dst_nanbox_unwrap_string(x)); printf("<string %p>\n", dst_nanbox_unwrap_string(x));
break; break;
case DST_T_SYMBOL: case DST_SYMBOL:
printf("<symbol %p>\n", dst_nanbox_unwrap_symbol(x)); printf("<symbol %p>\n", dst_nanbox_unwrap_symbol(x));
break; break;
case DST_T_USERDATA: case DST_USERDATA:
printf("<userdata %p>\n", dst_nanbox_unwrap_userdata(x)); printf("<userdata %p>\n", dst_nanbox_unwrap_userdata(x));
break; break;
case DST_T_FUNCTION: case DST_FUNCTION:
printf("<function %p>\n", dst_nanbox_unwrap_function(x)); printf("<function %p>\n", dst_nanbox_unwrap_function(x));
break; break;
case DST_T_CFUNCTION: case DST_CFUNCTION:
printf("<cfunction %p>\n", dst_nanbox_unwrap_cfunction(x)); printf("<cfunction %p>\n", dst_nanbox_unwrap_cfunction(x));
break; break;
case DST_T_BUFFER: case DST_BUFFER:
printf("<buffer %p>\n", dst_nanbox_unwrap_buffer(x)); printf("<buffer %p>\n", dst_nanbox_unwrap_buffer(x));
break; break;
default: default:
printf("unknown type 0x%lu\n", dst_nanbox_type(x)); printf("unknown type 0x%lu\n", dst_nanbox_type(x));
case DST_T_REAL: case DST_REAL:
printf("%.21g\n", dst_nanbox_unwrap_real(x)); printf("%.21g\n", dst_nanbox_unwrap_real(x));
break; break;
} }
assert(dst_nanbox_checktype(x, dst_nanbox_type(x)));
} }
int main() { int main() {
@ -242,6 +229,10 @@ int main() {
DstArray array; DstArray array;
dst_t a = dst_nanbox_wrap_real(0.123);
dst_t b = dst_nanbox_wrap_nil();
dst_nanbox_print(dst_nanbox_wrap_real(dst_nanbox_unwrap_real(a) + dst_nanbox_unwrap_real(b)));
dst_nanbox_print(dst_nanbox_wrap_real(0.125)); dst_nanbox_print(dst_nanbox_wrap_real(0.125));
dst_nanbox_print(dst_nanbox_wrap_real(19236910.125)); dst_nanbox_print(dst_nanbox_wrap_real(19236910.125));
dst_nanbox_print(dst_nanbox_wrap_real(123120.125)); dst_nanbox_print(dst_nanbox_wrap_real(123120.125));
@ -252,6 +243,7 @@ int main() {
dst_nanbox_print(dst_nanbox_wrap_real(0.0/0.0)); dst_nanbox_print(dst_nanbox_wrap_real(0.0/0.0));
dst_nanbox_print(dst_nanbox_wrap_true()); dst_nanbox_print(dst_nanbox_wrap_true());
dst_nanbox_print(dst_nanbox_wrap_false()); dst_nanbox_print(dst_nanbox_wrap_false());
dst_nanbox_print(dst_nanbox_wrap_nil());
dst_nanbox_print(dst_nanbox_wrap_integer(123)); dst_nanbox_print(dst_nanbox_wrap_integer(123));
dst_nanbox_print(dst_nanbox_wrap_integer(-123)); dst_nanbox_print(dst_nanbox_wrap_integer(-123));
dst_nanbox_print(dst_nanbox_wrap_integer(0)); dst_nanbox_print(dst_nanbox_wrap_integer(0));