diff --git a/core/array.c b/core/array.c index 8672013c..3d3a1f06 100644 --- a/core/array.c +++ b/core/array.c @@ -23,7 +23,8 @@ #include /* 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); if (NULL == data) { DST_OUT_OF_MEMORY; @@ -39,13 +40,13 @@ void dst_array_deinit(DstArray *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)); return dst_array_init(array, capacity); } /* 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 *old = array->data; 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. */ -void dst_array_setcount(DstArray *array, uint32_t count) { +void dst_array_setcount(DstArray *array, int32_t count) { if (count > array->count) { - uint32_t i; dst_array_ensure(array, count + 1); - for (i = array->count; i < count; ++i) - array->data[i].type = DST_NIL; + dst_memempty(array->data + array->count, count - array->count); } - array->count = count; + if (count > 0) + array->count = count; } /* Push a value to the top of the array */ void dst_array_push(DstArray *array, DstValue x) { - uint32_t newcount = array->count + 1; + int32_t newcount = array->count + 1; if (newcount >= array->capacity) { dst_array_ensure(array, newcount * 2); } diff --git a/core/asm.c b/core/asm.c index 6dee2b67..92e38490 100644 --- a/core/asm.c +++ b/core/asm.c @@ -93,8 +93,8 @@ struct DstAssembler { jmp_buf on_error; const uint8_t *errmessage; - uint32_t environments_capacity; - uint32_t bytecode_count; /* Used for calculating labels */ + int32_t environments_capacity; + int32_t bytecode_count; /* Used for calculating labels */ DstTable labels; /* symbol -> bytecode 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 * binary search for the instruction definition. */ static int dst_strcompare(const uint8_t *str, const char *other) { - uint32_t len = dst_string_length(str); - uint32_t index; + int32_t len = dst_string_length(str); + int32_t index; for (index = 0; index < len; index++) { uint8_t c = str[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 * index of the matching test_string, or -1 if not found. */ -static int strsearch(const uint8_t *str, const char **test_strings) { - uint32_t len = dst_string_length(str); +static int32_t strsearch(const uint8_t *str, const char **test_strings) { + int32_t len = dst_string_length(str); int index; for (index = 0; ; index++) { - uint32_t i; + int32_t i; const char *testword = test_strings[index]; if (NULL == testword) 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 * integer. This integer will need to be trimmed and bound checked. */ -static int64_t doarg_1(DstAssembler *a, DstOpArgType argtype, DstValue x) { - int64_t ret = -1; +static int32_t doarg_1(DstAssembler *a, DstOpArgType argtype, DstValue x) { + int32_t ret = -1; DstTable *c; switch (argtype) { case DST_OAT_SLOT: @@ -267,20 +267,21 @@ static int64_t doarg_1(DstAssembler *a, DstOpArgType argtype, DstValue x) { c = &a->labels; break; } - switch (x.type) { + switch (dst_type(x)) { default: goto error; break; case DST_INTEGER: - ret = x.as.integer; + ret = dst_unwrap_integer(x); break; case DST_TUPLE: { + const DstValue *t = dst_unwrap_tuple(x); if (argtype == DST_OAT_TYPE) { + int32_t i = 0; ret = 0; - uint32_t i = 0; - for (i = 0; i < dst_tuple_length(x.as.tuple); i++) { - ret |= doarg_1(a, DST_OAT_SIMPLETYPE, x.as.tuple[i]); + for (i = 0; i < dst_tuple_length(t); i++) { + ret |= doarg_1(a, DST_OAT_SIMPLETYPE, t[i]); } } else { goto error; @@ -288,24 +289,22 @@ static int64_t doarg_1(DstAssembler *a, DstOpArgType argtype, DstValue x) { break; } case DST_SYMBOL: - case DST_STRING: { - x.type = DST_SYMBOL; if (NULL != c) { DstValue result = dst_table_get(c, x); - if (result.type == DST_INTEGER) { + if (dst_checktype(result, DST_INTEGER)) { if (argtype == DST_OAT_LABEL) { - ret = result.as.integer - a->bytecode_count; + ret = dst_unwrap_integer(result) - a->bytecode_count; } else { - ret = result.as.integer; + ret = dst_unwrap_integer(result); } } else { dst_asm_errorv(a, dst_formatc("unknown name %q", x)); } } 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) { - ret = (int64_t) index; + ret = index; } else { 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) - a->def->slotcount = (uint32_t) ret + 1; + a->def->slotcount = (int32_t) ret + 1; return ret; error: @@ -333,18 +332,18 @@ static uint32_t doarg( int nbytes, int hassign, 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 * nbytes, and whether or not the storage is signed */ - int64_t min = (-hassign) << ((nbytes << 3) - 1); - int64_t max = ~((-1) << ((nbytes << 3) - hassign)); + int32_t min = (-hassign) << ((nbytes << 3) - 1); + int32_t max = ~((-1) << ((nbytes << 3) - hassign)); if (arg < min) dst_asm_errorv(a, dst_formatc("instruction argument %v is too small, must be %d byte%s", x, nbytes, nbytes > 1 ? "s" : "")); if (arg > max) dst_asm_errorv(a, dst_formatc("instruction argument %v is too large, must be %d byte%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 */ @@ -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. * Returns the index of the environment in the assembler's environments, or -1 * 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; DstFuncDef *def = a->def; - uint32_t oldlen; + int32_t oldlen; int64_t res; /* Check for memoized value */ check = dst_table_get(&a->envs, envname); - if (check.type != DST_NIL) { - return check.as.integer; + if (!dst_checktype(check, DST_NIL)) { + return dst_unwrap_integer(check); } if (NULL == a->parent) { return -1; @@ -475,24 +474,24 @@ static int64_t dst_asm_addenv(DstAssembler *a, DstValue envname) { oldlen = def->environments_length; dst_table_put(&a->envs, envname, dst_wrap_integer(def->environments_length)); if (oldlen >= a->environments_capacity) { - uint32_t newcap = 2 + 2 * oldlen; - def->environments = realloc(def->environments, newcap * sizeof(uint32_t)); + int32_t newcap = 2 + 2 * oldlen; + def->environments = realloc(def->environments, newcap * sizeof(int32_t)); if (NULL == def->environments) { DST_OUT_OF_MEMORY; } a->environments_capacity = newcap; } - def->environments[def->environments_length++] = (uint32_t) res; - return (int64_t) oldlen; + def->environments[def->environments_length++] = (int32_t) res; + return (int32_t) oldlen; } /* Helper to assembly. Return the assembly result */ static DstAssembleResult dst_asm1(DstAssembler *parent, DstAssembleOptions opts) { DstAssembleResult result; DstAssembler a; - const DstValue *st = opts.source.as.st; + const DstValue *st = dst_unwrap_struct(opts.source); DstFuncDef *def; - uint32_t count, i; + int32_t count, i; const DstValue *arr; DstValue x; @@ -530,25 +529,26 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, DstAssembleOptions opts) 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 */ 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 */ x = dst_struct_get(st, dst_csymbolv("slots")); if (dst_seq_view(x, &arr, &count)) { for (i = 0; i < count; i++) { DstValue v = arr[i]; - if (v.type == DST_TUPLE) { - uint32_t j; - for (j = 0; j < dst_tuple_length(v.as.tuple); j++) { - if (v.as.tuple[j].type != DST_SYMBOL) + if (dst_checktype(v, DST_TUPLE)) { + const DstValue *t = dst_unwrap_tuple(v); + int32_t j; + 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_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)); } else { 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")); if (dst_seq_view(x, &arr, &count)) { 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) { 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++) { DstValue ct = arr[i]; - if (ct.type == DST_TUPLE && - dst_tuple_length(ct.as.tuple) > 1 && - ct.as.tuple[0].type == DST_SYMBOL) { - uint32_t tcount = dst_tuple_length(ct.as.tuple); - const uint8_t *macro = ct.as.tuple[0].as.string; + if (dst_checktype(ct, DST_TUPLE) && + dst_tuple_length(dst_unwrap_tuple(ct)) > 1 && + dst_checktype(dst_unwrap_tuple(ct)[0], DST_SYMBOL)) { + const DstValue *t = dst_unwrap_tuple(ct); + int32_t tcount = dst_tuple_length(t); + const uint8_t *macro = dst_unwrap_symbol(t[0]); if (0 == dst_strcompare(macro, "quote")) { - def->constants[i] = ct.as.tuple[1]; + def->constants[i] = t[1]; } else if (tcount == 3 && - ct.as.tuple[1].type == DST_SYMBOL && + dst_checktype(t[1], DST_SYMBOL) && 0 == dst_strcompare(macro, "def")) { - def->constants[i] = ct.as.tuple[2]; - dst_table_put(&a.constants, ct.as.tuple[1], dst_wrap_integer(i)); + def->constants[i] = t[2]; + dst_table_put(&a.constants, t[1], dst_wrap_integer(i)); } else { 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")); if (dst_seq_view(x, &arr, &count)) { /* Do labels and find length */ - uint32_t blength = 0; + int32_t blength = 0; for (i = 0; i < count; ++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)); - } else if (instr.type == DST_TUPLE) { + } else if (dst_checktype(instr, DST_TUPLE)) { blength++; } else { dst_asm_error(&a, "expected assembly instruction"); @@ -619,28 +620,30 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, DstAssembleOptions opts) } /* Allocate bytecode array */ def->bytecode_length = blength; - def->bytecode = malloc(sizeof(uint32_t) * blength); + def->bytecode = malloc(sizeof(int32_t) * blength); if (NULL == def->bytecode) { DST_OUT_OF_MEMORY; } /* Do bytecode */ for (i = 0; i < count; ++i) { DstValue instr = arr[i]; - if (instr.type == DST_SYMBOL) { + if (dst_checktype(instr, DST_SYMBOL)) { continue; } else { uint32_t op; const DstInstructionDef *idef; - dst_asm_assert(&a, instr.type == DST_TUPLE, "expected tuple"); - if (dst_tuple_length(instr.as.tuple) == 0) { + const DstValue *t; + dst_asm_assert(&a, dst_checktype(instr, DST_TUPLE), "expected tuple"); + t = dst_unwrap_tuple(instr); + if (dst_tuple_length(t) == 0) { op = 0; } 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"); - idef = dst_findi(instr.as.tuple[0].as.string); + idef = dst_findi(dst_unwrap_symbol(t[0])); if (NULL == idef) 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; } @@ -652,7 +655,7 @@ static DstAssembleResult dst_asm1(DstAssembler *parent, DstAssembleOptions opts) /* Finish everything and return funcdef */ dst_asm_deinit(&a); 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.status = DST_ASSEMBLE_OK; return result; diff --git a/core/buffer.c b/core/buffer.c index 2106cc6f..6dbd337b 100644 --- a/core/buffer.c +++ b/core/buffer.c @@ -23,7 +23,7 @@ #include /* 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; if (capacity > 0) { data = malloc(sizeof(uint8_t) * capacity); @@ -43,13 +43,13 @@ void dst_buffer_deinit(DstBuffer *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)); return dst_buffer_init(buffer, 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 *old = buffer->data; 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 * next n bytes pushed to the buffer will not cause a reallocation */ -void dst_buffer_extra(DstBuffer *buffer, uint32_t n) { - uint32_t new_size = buffer->count + n; +void dst_buffer_extra(DstBuffer *buffer, int32_t n) { + int32_t new_size = buffer->count + n; 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)); if (NULL == new_data) { DST_OUT_OF_MEMORY; @@ -77,8 +77,8 @@ void dst_buffer_extra(DstBuffer *buffer, uint32_t n) { } /* Push multiple bytes into the buffer */ -void dst_buffer_push_bytes(DstBuffer *buffer, const uint8_t *string, uint32_t length) { - uint32_t new_size = buffer->count + length; +void dst_buffer_push_bytes(DstBuffer *buffer, const uint8_t *string, int32_t length) { + int32_t new_size = buffer->count + length; dst_buffer_ensure(buffer, new_size); memcpy(buffer->data + buffer->count, string, length); 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 */ void dst_buffer_push_cstring(DstBuffer *buffer, const char *cstring) { - uint32_t len = 0; + int32_t len = 0; while (cstring[len]) ++len; dst_buffer_push_bytes(buffer, (const uint8_t *) cstring, len); } /* Push a single byte to the buffer */ 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); buffer->data[buffer->count] = byte; 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 */ 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); buffer->data[buffer->count] = x & 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 */ 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); buffer->data[buffer->count] = x & 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 */ 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); buffer->data[buffer->count] = x & 0xFF; buffer->data[buffer->count + 1] = (x >> 8) & 0xFF; diff --git a/core/fiber.c b/core/fiber.c index 91f43ac6..148bfc0c 100644 --- a/core/fiber.c +++ b/core/fiber.c @@ -23,7 +23,7 @@ #include /* 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)); fiber->capacity = capacity; if (capacity) { @@ -51,7 +51,7 @@ DstFiber *dst_fiber_reset(DstFiber *fiber) { } /* 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); if (NULL == newData) { DST_OUT_OF_MEMORY; @@ -70,7 +70,7 @@ void dst_fiber_push(DstFiber *fiber, DstValue x) { /* Push 2 values on the next stack frame */ 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) { 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 */ 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) { 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 */ -void dst_fiber_pushn(DstFiber *fiber, const DstValue *arr, uint32_t n) { - uint32_t newtop = fiber->stacktop + n; +void dst_fiber_pushn(DstFiber *fiber, const DstValue *arr, int32_t n) { + int32_t newtop = fiber->stacktop + n; if (newtop > fiber->capacity) { 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. * If there is nothing to pop of of the stack, return nil. */ DstValue dst_fiber_popvalue(DstFiber *fiber) { - uint32_t newstacktop = fiber->stacktop - 1; - if (newstacktop < fiber->frametop + DST_FRAME_SIZE) { + int32_t newstacktop = fiber->stacktop - 1; + if (newstacktop < fiber->frametop + (int32_t)(DST_FRAME_SIZE)) { return dst_wrap_nil(); } fiber->stacktop = newstacktop; @@ -116,11 +116,11 @@ DstValue dst_fiber_popvalue(DstFiber *fiber) { void dst_fiber_funcframe(DstFiber *fiber, DstFunction *func) { DstStackFrame *newframe; - uint32_t i; - uint32_t oldframe = fiber->frame; - uint32_t nextframe = fiber->frametop + DST_FRAME_SIZE; - uint32_t nextframetop = nextframe + func->def->slotcount; - uint32_t nextstacktop = nextframetop + DST_FRAME_SIZE; + int32_t i; + int32_t oldframe = fiber->frame; + int32_t nextframe = fiber->frametop + DST_FRAME_SIZE; + int32_t nextframetop = nextframe + func->def->slotcount; + int32_t nextstacktop = nextframetop + DST_FRAME_SIZE; if (fiber->capacity < 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) */ for (i = fiber->stacktop; i < fiber->frametop; ++i) { - fiber->data[i].type = DST_NIL; + fiber->data[i] = dst_wrap_nil(); } /* Check varargs */ 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) { fiber->data[tuplehead] = dst_wrap_tuple(dst_tuple_n(NULL, 0)); } else { @@ -159,11 +159,11 @@ void dst_fiber_funcframe(DstFiber *fiber, DstFunction *func) { /* Create a tail frame for a function */ void dst_fiber_funcframe_tail(DstFiber *fiber, DstFunction *func) { - uint32_t i; - uint32_t nextframetop = fiber->frame + func->def->slotcount; - uint32_t nextstacktop = nextframetop + DST_FRAME_SIZE; - uint32_t size = (fiber->stacktop - fiber->frametop) - DST_FRAME_SIZE; - uint32_t argtop = fiber->frame + size; + int32_t i; + int32_t nextframetop = fiber->frame + func->def->slotcount; + int32_t nextstacktop = nextframetop + DST_FRAME_SIZE; + int32_t size = (fiber->stacktop - fiber->frametop) - DST_FRAME_SIZE; + int32_t argtop = fiber->frame + size; if (fiber->capacity < 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) */ for (i = fiber->frame + size; i < fiber->frametop; ++i) { - fiber->data[i].type = DST_NIL; + fiber->data[i] = dst_wrap_nil(); } /* Check varargs */ 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) { fiber->data[tuplehead] = dst_wrap_tuple(dst_tuple_n(NULL, 0)); } else { @@ -208,10 +208,10 @@ void dst_fiber_funcframe_tail(DstFiber *fiber, DstFunction *func) { void dst_fiber_cframe(DstFiber *fiber) { DstStackFrame *newframe; - uint32_t oldframe = fiber->frame; - uint32_t nextframe = fiber->frametop + DST_FRAME_SIZE; - uint32_t nextframetop = fiber->stacktop; - uint32_t nextstacktop = nextframetop + DST_FRAME_SIZE; + int32_t oldframe = fiber->frame; + int32_t nextframe = fiber->frametop + DST_FRAME_SIZE; + int32_t nextframetop = fiber->stacktop; + int32_t nextstacktop = nextframetop + DST_FRAME_SIZE; if (fiber->capacity < nextstacktop) { dst_fiber_setcapacity(fiber, 2 * nextstacktop); @@ -231,9 +231,9 @@ void dst_fiber_cframe(DstFiber *fiber) { /* Create a cframe for a tail call */ void dst_fiber_cframe_tail(DstFiber *fiber) { - uint32_t size = (fiber->stacktop - fiber->frametop) - DST_FRAME_SIZE; - uint32_t nextframetop = fiber->frame + size;; - uint32_t nextstacktop = nextframetop + DST_FRAME_SIZE; + int32_t size = (fiber->stacktop - fiber->frametop) - DST_FRAME_SIZE; + int32_t nextframetop = fiber->frame + size;; + int32_t nextstacktop = nextframetop + DST_FRAME_SIZE; if (fiber->frame == 0) { return dst_fiber_cframe(fiber); diff --git a/core/gc.c b/core/gc.c index aaf77626..3fb989ef 100644 --- a/core/gc.c +++ b/core/gc.c @@ -43,18 +43,18 @@ static void dst_mark_udata(void *udata); /* Mark a value */ void dst_mark(DstValue x) { - switch (x.type) { + switch (dst_type(x)) { default: break; case DST_STRING: - case DST_SYMBOL: dst_mark_string(x.as.string); break; - case DST_FUNCTION: dst_mark_function(x.as.function); break; - case DST_ARRAY: dst_mark_array(x.as.array); break; - case DST_TABLE: dst_mark_table(x.as.table); break; - case DST_STRUCT: dst_mark_struct(x.as.st); break; - case DST_TUPLE: dst_mark_tuple(x.as.tuple); break; - case DST_BUFFER: dst_mark_buffer(x.as.buffer); break; - case DST_FIBER: dst_mark_fiber(x.as.fiber); break; - case DST_USERDATA: dst_mark_udata(x.as.pointer); break; + case DST_SYMBOL: dst_mark_string(dst_unwrap_string(x)); break; + case DST_FUNCTION: dst_mark_function(dst_unwrap_function(x)); break; + case DST_ARRAY: dst_mark_array(dst_unwrap_array(x)); break; + case DST_TABLE: dst_mark_table(dst_unwrap_table(x)); break; + case DST_STRUCT: dst_mark_struct(dst_unwrap_struct(x)); break; + case DST_TUPLE: dst_mark_tuple(dst_unwrap_tuple(x)); break; + case DST_BUFFER: dst_mark_buffer(dst_unwrap_buffer(x)); break; + case DST_FIBER: dst_mark_fiber(dst_unwrap_fiber(x)); 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 * the gc cannot inspect). */ void dst_pin(DstValue x) { - switch (x.type) { + switch (dst_type(x)) { default: break; case DST_STRING: - case DST_SYMBOL: dst_pin_string(x.as.string); break; - case DST_FUNCTION: dst_pin_function(x.as.function); break; - case DST_ARRAY: dst_pin_array(x.as.array); break; - case DST_TABLE: dst_pin_table(x.as.table); break; - case DST_STRUCT: dst_pin_struct(x.as.st); break; - case DST_TUPLE: dst_pin_tuple(x.as.tuple); break; - case DST_BUFFER: dst_pin_buffer(x.as.buffer); break; - case DST_FIBER: dst_pin_fiber(x.as.fiber); break; - case DST_USERDATA: dst_pin_userdata(x.as.pointer); break; + case DST_SYMBOL: dst_pin_string(dst_unwrap_string(x)); break; + case DST_FUNCTION: dst_pin_function(dst_unwrap_function(x)); break; + case DST_ARRAY: dst_pin_array(dst_unwrap_array(x)); break; + case DST_TABLE: dst_pin_table(dst_unwrap_table(x)); break; + case DST_STRUCT: dst_pin_struct(dst_unwrap_struct(x)); break; + case DST_TUPLE: dst_pin_tuple(dst_unwrap_tuple(x)); break; + case DST_BUFFER: dst_pin_buffer(dst_unwrap_buffer(x)); break; + case DST_FIBER: dst_pin_fiber(dst_unwrap_fiber(x)); break; + case DST_USERDATA: dst_pin_userdata(dst_unwrap_pointer(x)); break; } } /* Unpin a value. This enables the GC to collect the value's * memory again. */ void dst_unpin(DstValue x) { - switch (x.type) { + switch (dst_type(x)) { default: break; case DST_STRING: - case DST_SYMBOL: dst_unpin_string(x.as.string); break; - case DST_FUNCTION: dst_unpin_function(x.as.function); break; - case DST_ARRAY: dst_unpin_array(x.as.array); break; - case DST_TABLE: dst_unpin_table(x.as.table); break; - case DST_STRUCT: dst_unpin_struct(x.as.st); break; - case DST_TUPLE: dst_unpin_tuple(x.as.tuple); break; - case DST_BUFFER: dst_unpin_buffer(x.as.buffer); break; - case DST_FIBER: dst_unpin_fiber(x.as.fiber); break; - case DST_USERDATA: dst_unpin_userdata(x.as.pointer); break; + case DST_SYMBOL: dst_unpin_string(dst_unwrap_string(x)); break; + case DST_FUNCTION: dst_unpin_function(dst_unwrap_function(x)); break; + case DST_ARRAY: dst_unpin_array(dst_unwrap_array(x)); break; + case DST_TABLE: dst_unpin_table(dst_unwrap_table(x)); break; + case DST_STRUCT: dst_unpin_struct(dst_unwrap_struct(x)); break; + case DST_TUPLE: dst_unpin_tuple(dst_unwrap_tuple(x)); break; + case DST_BUFFER: dst_unpin_buffer(dst_unwrap_buffer(x)); break; + case DST_FIBER: dst_unpin_fiber(dst_unwrap_fiber(x)); 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 */ -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; while (values < end) { dst_mark(*values); @@ -163,7 +163,7 @@ static void dst_mark_funcenv(DstFuncEnv *env) { /* GC helper to mark a FuncDef */ static void dst_mark_funcdef(DstFuncDef *def) { - uint32_t count, i; + int32_t count, i; if (dst_gc_reachable(def)) return; dst_gc_mark(def); @@ -171,9 +171,9 @@ static void dst_mark_funcdef(DstFuncDef *def) { count = def->constants_length; for (i = 0; i < count; ++i) { DstValue v = def->constants[i]; - /* Funcdefs use boolean literals to store other funcdefs */ - if (v.type == DST_BOOLEAN) { - dst_mark_funcdef((DstFuncDef *) v.as.pointer); + /* Funcdefs use nil literals to store other funcdefs */ + if (v.type == DST_NIL) { + dst_mark_funcdef((DstFuncDef *) dst_unwrap_pointer(v)); } else { dst_mark(v); } @@ -182,8 +182,8 @@ static void dst_mark_funcdef(DstFuncDef *def) { } static void dst_mark_function(DstFunction *func) { - uint32_t i; - uint32_t numenvs; + int32_t i; + int32_t numenvs; if (dst_gc_reachable(func)) return; dst_gc_mark(func); @@ -196,7 +196,7 @@ static void dst_mark_function(DstFunction *func) { } static void dst_mark_fiber(DstFiber *fiber) { - uint32_t i, j; + int32_t i, j; DstStackFrame *frame; if (dst_gc_reachable(fiber)) return; @@ -204,7 +204,7 @@ static void dst_mark_fiber(DstFiber *fiber) { i = fiber->frame; j = fiber->frametop; - while (i != 0) { + while (i > 0) { frame = (DstStackFrame *)(fiber->data + i - DST_FRAME_SIZE); if (NULL != frame->func) dst_mark_function(frame->func); @@ -228,7 +228,7 @@ static void dst_deinit_block(DstGCMemoryHeader *block) { default: break; /* Do nothing for non gc types */ 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; case DST_MEMORY_ARRAY: dst_array_deinit((DstArray*) mem); diff --git a/core/parse.c b/core/parse.c index 51efb93e..13bb6194 100644 --- a/core/parse.c +++ b/core/parse.c @@ -172,10 +172,10 @@ typedef struct { static const uint8_t *parse_recur( ParseArgs *args, const uint8_t *src, - uint32_t recur) { + int32_t recur) { const uint8_t *end = args->end; - uint32_t qcount = 0; + int32_t qcount = 0; DstValue ret; /* Prevent stack overflow */ @@ -243,7 +243,7 @@ static const uint8_t *parse_recur( { const uint8_t *strend = ++src; const uint8_t *strstart = strend; - uint32_t len = 0; + int32_t len = 0; int containsEscape = 0; /* Preprocess string to check for escapes and string end */ while (strend < end && *strend != '"') { @@ -306,8 +306,8 @@ static const uint8_t *parse_recur( case '[': case '{': { - uint32_t n = 0, i = 0; - uint32_t istable = 0; + int32_t n = 0, i = 0; + int32_t istable = 0; uint8_t close; switch (*src++) { 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. */ -DstParseResult dst_parse(const uint8_t *src, uint32_t len) { +DstParseResult dst_parse(const uint8_t *src, int32_t len) { DstParseResult res; ParseArgs args; 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); res.status = args.status; - res.bytes_read = (uint32_t) (newsrc - src); + res.bytes_read = (int32_t) (newsrc - src); /* TODO - source maps */ res.map = dst_wrap_nil(); @@ -451,7 +451,7 @@ DstParseResult dst_parse(const uint8_t *src, uint32_t len) { /* Parse a c string */ DstParseResult dst_parsec(const char *src) { - uint32_t len = 0; + int32_t len = 0; while (src[len]) ++len; return dst_parse((const uint8_t *)src, len); } diff --git a/core/string.c b/core/string.c index 4ccf2493..e447851e 100644 --- a/core/string.c +++ b/core/string.c @@ -23,9 +23,9 @@ #include /* Begin building a string */ -uint8_t *dst_string_begin(uint32_t length) { - char *data = dst_alloc(DST_MEMORY_STRING, 2 * sizeof(uint32_t) + length); - uint8_t *str = (uint8_t *) (data + 2 * sizeof(uint32_t)); +uint8_t *dst_string_begin(int32_t length) { + char *data = dst_alloc(DST_MEMORY_STRING, 2 * sizeof(int32_t) + length); + uint8_t *str = (uint8_t *) (data + 2 * sizeof(int32_t)); dst_string_length(str) = length; return str; } @@ -37,10 +37,10 @@ const uint8_t *dst_string_end(uint8_t *str) { } /* Load a buffer as a string */ -const uint8_t *dst_string(const uint8_t *buf, uint32_t len) { - uint32_t hash = dst_string_calchash(buf, len); - char *data = dst_alloc(DST_MEMORY_STRING, 2 * sizeof(uint32_t) + len); - uint8_t *str = (uint8_t *) (data + 2 * sizeof(uint32_t)); +const uint8_t *dst_string(const uint8_t *buf, int32_t len) { + int32_t hash = dst_string_calchash(buf, len); + char *data = dst_alloc(DST_MEMORY_STRING, 2 * sizeof(int32_t) + len); + uint8_t *str = (uint8_t *) (data + 2 * sizeof(int32_t)); memcpy(str, buf, len); dst_string_length(str) = len; dst_string_hash(str) = hash; @@ -49,10 +49,10 @@ const uint8_t *dst_string(const uint8_t *buf, uint32_t len) { /* Compare two strings */ int dst_string_compare(const uint8_t *lhs, const uint8_t *rhs) { - uint32_t xlen = dst_string_length(lhs); - uint32_t ylen = dst_string_length(rhs); - uint32_t len = xlen > ylen ? ylen : xlen; - uint32_t i; + int32_t xlen = dst_string_length(lhs); + int32_t ylen = dst_string_length(rhs); + int32_t len = xlen > ylen ? ylen : xlen; + int32_t i; for (i = 0; i < len; ++i) { if (lhs[i] == rhs[i]) { 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 */ -int dst_string_equalconst(const uint8_t *lhs, const uint8_t *rhs, uint32_t rlen, uint32_t rhash) { - uint32_t index; - uint32_t lhash = dst_string_hash(lhs); - uint32_t llen = dst_string_length(lhs); +int dst_string_equalconst(const uint8_t *lhs, const uint8_t *rhs, int32_t rlen, int32_t rhash) { + int32_t index; + int32_t lhash = dst_string_hash(lhs); + int32_t llen = dst_string_length(lhs); if (lhs == rhs) return 1; 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 */ const uint8_t *dst_cstring(const char *str) { - uint32_t len = 0; + int32_t len = 0; while (str[len]) ++len; return dst_string((const uint8_t *)str, len); } @@ -101,9 +101,9 @@ const uint8_t *dst_cstring(const char *str) { /* Temporary buffer size */ #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); - return (uint32_t) count; + return (int32_t) count; } 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)); } -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; uint8_t *hi, *low; - uint32_t count = 0; + int32_t count = 0; if (x == 0) { buf[0] = '0'; return 1; @@ -160,9 +160,9 @@ static const uint8_t *integer_to_string(int64_t x) { /* Returns a string description for a pointer. Truncates * 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; - uint32_t i; + int32_t i; union { uint8_t bytes[sizeof(void *)]; 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++ = '>'; - return (uint32_t) (c - buf); + return (int32_t) (c - buf); } 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 DST_BUFSIZE -static uint32_t dst_escape_string_length(const uint8_t *str) { - uint32_t len = 2; - uint32_t i; +static int32_t dst_escape_string_length(const uint8_t *str) { + int32_t len = 2; + int32_t i; for (i = 0; i < dst_string_length(str); ++i) { switch (str[i]) { 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) { - uint32_t i, j; + int32_t i, j; buf[0] = '"'; for (i = 0, j = 1; i < dst_string_length(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) { - uint32_t len = dst_escape_string_length(str); + int32_t len = dst_escape_string_length(str); dst_buffer_extra(buffer, len); dst_escape_string_impl(buffer->data + buffer->count, str); buffer->count += len; } 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); dst_escape_string_impl(buf, str); 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 */ const uint8_t *dst_short_description(DstValue x) { - switch (x.type) { + switch (dst_type(x)) { case DST_NIL: return dst_cstring("nil"); - case DST_BOOLEAN: - if (x.as.boolean) - return dst_cstring("true"); - else - return dst_cstring("false"); + case DST_TRUE: + return dst_cstring("true"); + case DST_FALSE: + return dst_cstring("false"); case DST_REAL: - return real_to_string(x.as.real); + return real_to_string(dst_unwrap_real(x)); case DST_INTEGER: - return integer_to_string(x.as.integer); + return integer_to_string(dst_unwrap_integer(x)); case DST_SYMBOL: - return x.as.string; + return dst_unwrap_string(x); case DST_STRING: - return dst_escape_string(x.as.string); + return dst_escape_string(dst_unwrap_string(x)); 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: - 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) { - switch (x.type) { + switch (dst_type(x)) { case DST_NIL: dst_buffer_push_cstring(buffer, "nil"); return; - case DST_BOOLEAN: - if (x.as.boolean) - dst_buffer_push_cstring(buffer, "true"); - else - dst_buffer_push_cstring(buffer, "false"); + case DST_TRUE: + dst_buffer_push_cstring(buffer, "true"); + return; + case DST_FALSE: + dst_buffer_push_cstring(buffer, "false"); return; case DST_REAL: - real_to_string_b(buffer, x.as.real); + real_to_string_b(buffer, dst_unwrap_real(x)); return; case DST_INTEGER: - integer_to_string_b(buffer, x.as.integer); + integer_to_string_b(buffer, dst_unwrap_integer(x)); return; 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; case DST_STRING: - dst_escape_string_b(buffer, x.as.string); + dst_escape_string_b(buffer, dst_unwrap_string(x)); return; 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; 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; } } @@ -327,10 +326,10 @@ struct DstPrinter { DstTable seen; uint32_t flags; int64_t next; - uint32_t indent; - uint32_t indent_size; - uint32_t token_line_limit; - uint32_t depth; + int32_t indent; + int32_t indent_size; + int32_t token_line_limit; + int32_t depth; }; #define DST_PRINTFLAG_INDENT 1 @@ -340,7 +339,7 @@ struct DstPrinter { /* Go to next line for printer */ static void dst_print_indent(DstPrinter *p) { - uint32_t i, len; + int32_t i, len; len = p->indent_size * p->indent; for (i = 0; i < len; i++) { 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) */ static int is_print_ds(DstValue v) { - switch (v.type) { + switch (dst_type(v)) { default: return 0; case DST_ARRAY: case DST_STRUCT: @@ -381,8 +380,8 @@ static const char *dst_type_colors[15] = { static void dst_description_helper(DstPrinter *p, DstValue x); /* Print a hastable view inline */ -static void dst_print_hashtable_inner(DstPrinter *p, const DstValue *data, uint32_t len, uint32_t cap) { - uint32_t i; +static void dst_print_hashtable_inner(DstPrinter *p, const DstValue *data, int32_t len, int32_t cap) { + int32_t i; int doindent = 0; if (p->flags & DST_PRINTFLAG_INDENT) { 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'); p->indent++; 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_description_helper(p, data[i]); dst_buffer_push_u8(&p->buffer, ' '); @@ -413,7 +412,7 @@ static void dst_print_hashtable_inner(DstPrinter *p, const DstValue *data, uint3 } else { int isfirst = 1; for (i = 0; i < cap; i += 2) { - if (data[i].type != DST_NIL) { + if (dst_checktype(data[i], DST_NIL)) { if (isfirst) isfirst = 0; else @@ -427,8 +426,8 @@ static void dst_print_hashtable_inner(DstPrinter *p, const DstValue *data, uint3 } /* Help print a sequence */ -static void dst_print_seq_inner(DstPrinter *p, const DstValue *data, uint32_t len) { - uint32_t i; +static void dst_print_seq_inner(DstPrinter *p, const DstValue *data, int32_t len) { + int32_t i; int doindent = 0; if (p->flags & DST_PRINTFLAG_INDENT) { 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) { p->depth--; 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, "buffer, check.as.integer); + integer_to_string_b(&p->buffer, dst_unwrap_integer(check)); dst_buffer_push_cstring(&p->buffer, ">"); } else { const char *open; const char *close; - uint32_t len, cap; + int32_t len, cap; const DstValue *data; - switch (x.type) { + switch (dst_type(x)) { default: 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_buffer_push_cstring(&p->buffer, "\x1B[0m"); } else { @@ -547,12 +546,12 @@ const uint8_t *dst_description(DstValue x) { /* Convert any value to a dst string. Similar to description, but * strings, symbols, and buffers will return their content. */ const uint8_t *dst_to_string(DstValue x) { - switch (x.type) { + switch (dst_type(x)) { default: return dst_short_description(x); case DST_STRING: 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. */ const uint8_t *dst_formatc(const char *format, ...) { va_list args; - uint32_t len = 0; - uint32_t i; + int32_t len = 0; + int32_t i; const uint8_t *ret; DstPrinter printer; DstBuffer *bufp = &printer.buffer; @@ -654,8 +653,8 @@ const uint8_t *dst_formatc(const char *format, ...) { /* Print string to stdout */ void dst_puts(const uint8_t *str) { - uint32_t i; - uint32_t len = dst_string_length(str); + int32_t i; + int32_t len = dst_string_length(str); for (i = 0; i < len; i++) { putc(str[i], stdout); } diff --git a/core/struct.c b/core/struct.c index 658c0501..94fcad9b 100644 --- a/core/struct.c +++ b/core/struct.c @@ -23,17 +23,17 @@ #include /* 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 * function of count, and hold at least enough space for count * 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 * 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); 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; /* Use the hash storage space as a counter to see how many items * 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 */ static const DstValue *dst_struct_find(const DstValue *st, DstValue key) { - uint32_t cap = dst_struct_capacity(st); - uint32_t index = (dst_hash(key) % cap) & (~1); - uint32_t i; + int32_t cap = dst_struct_capacity(st); + int32_t index = (dst_hash(key) % cap) & (~1); + int32_t i; for (i = index; i < cap; i += 2) if (st[i].type == DST_NIL || dst_equals(st[i], key)) 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 * ignored. */ void dst_struct_put(DstValue *st, DstValue key, DstValue value) { - uint32_t cap = dst_struct_capacity(st); - uint32_t hash = dst_hash(key); - uint32_t index = (hash % cap) & (~1); - uint32_t i, j, dist; - uint32_t bounds[4] = {index, cap, 0, index}; + int32_t cap = dst_struct_capacity(st); + int32_t hash = dst_hash(key); + int32_t index = (hash % cap) & (~1); + int32_t i, j, dist; + int32_t bounds[4] = {index, cap, 0, index}; if (key.type == DST_NIL || value.type == DST_NIL) return; /* Avoid extra items */ if (dst_struct_hash(st) == dst_struct_length(st)) return; for (dist = 0, j = 0; j < 4; j += 2) for (i = bounds[j]; i < bounds[j + 1]; i += 2, dist += 2) { 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 */ if (st[i].type == DST_NIL) { st[i] = key; @@ -126,7 +127,7 @@ const DstValue *dst_struct_end(DstValue *st) { /* Error building struct, probably duplicate values. We need to rebuild * the struct using only the values that went in. The second creation should always * succeed. */ - uint32_t i, realCount; + int32_t i, realCount; DstValue *newst; realCount = 0; 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 */ DstTable *dst_struct_to_table(const DstValue *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) { if (st[i].type != DST_NIL) { 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 */ int dst_struct_equal(const DstValue *lhs, const DstValue *rhs) { - uint32_t index; - uint32_t llen = dst_struct_capacity(lhs); - uint32_t rlen = dst_struct_capacity(rhs); - uint32_t lhash = dst_struct_hash(lhs); - uint32_t rhash = dst_struct_hash(rhs); + int32_t index; + int32_t llen = dst_struct_capacity(lhs); + int32_t rlen = dst_struct_capacity(rhs); + int32_t lhash = dst_struct_hash(lhs); + int32_t rhash = dst_struct_hash(rhs); if (llen != rlen) return 0; if (lhash == 0) @@ -211,11 +212,11 @@ int dst_struct_equal(const DstValue *lhs, const DstValue *rhs) { /* Compare structs */ int dst_struct_compare(const DstValue *lhs, const DstValue *rhs) { - uint32_t i; - uint32_t lhash = dst_struct_hash(lhs); - uint32_t rhash = dst_struct_hash(rhs); - uint32_t llen = dst_struct_capacity(lhs); - uint32_t rlen = dst_struct_capacity(rhs); + int32_t i; + int32_t lhash = dst_struct_hash(lhs); + int32_t rhash = dst_struct_hash(rhs); + int32_t llen = dst_struct_capacity(lhs); + int32_t rlen = dst_struct_capacity(rhs); if (llen < rlen) return -1; if (llen > rlen) diff --git a/core/symcache.c b/core/symcache.c index fa0a5bad..a67bc570 100644 --- a/core/symcache.c +++ b/core/symcache.c @@ -61,11 +61,11 @@ void dst_symcache_deinit() { * where one would put it. */ static const uint8_t **dst_symcache_findmem( const uint8_t *str, - uint32_t len, - uint32_t hash, + int32_t len, + int32_t hash, int *success) { - uint32_t bounds[4]; - uint32_t i, j, index; + int32_t bounds[4]; + int32_t i, j, index; const uint8_t **firstEmpty = NULL; /* 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)) /* Resize the cache. */ -static void dst_cache_resize(uint32_t newCapacity) { - uint32_t i, oldCapacity; +static void dst_cache_resize(int32_t newCapacity) { + int32_t i, oldCapacity; const uint8_t **oldCache = dst_vm_cache; const uint8_t **newCache = calloc(1, newCapacity * sizeof(const uint8_t **)); if (newCache == NULL) { @@ -163,15 +163,15 @@ void dst_symbol_deinit(const uint8_t *sym) { } /* Create a symbol from a byte string */ -const uint8_t *dst_symbol(const uint8_t *str, uint32_t len) { - uint32_t hash = dst_string_calchash(str, len); +const uint8_t *dst_symbol(const uint8_t *str, int32_t len) { + int32_t hash = dst_string_calchash(str, len); uint8_t *newstr; int success = 0; const uint8_t **bucket = dst_symcache_findmem(str, len, hash, &success); if (success) return *bucket; - newstr = dst_alloc(DST_MEMORY_SYMBOL, 2 * sizeof(uint32_t) + len) - + (2 * sizeof(uint32_t)); + newstr = dst_alloc(DST_MEMORY_SYMBOL, 2 * sizeof(int32_t) + len) + + (2 * sizeof(int32_t)); dst_string_hash(newstr) = hash; dst_string_length(newstr) = 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 */ const uint8_t *dst_csymbol(const char *cstr) { - uint32_t len = 0; + int32_t len = 0; while (cstr[len]) 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 * symbol will be of the format prefix--XXXXXX, where X is a base64 digit, and * 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; - uint32_t hash; + int32_t hash; 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 * is enough for resolving collisions. */ - uint32_t newlen = len + 8; - uint32_t newbufsize = newlen + 2 * sizeof(uint32_t); - uint8_t *str = (uint8_t *)(dst_alloc(DST_MEMORY_SYMBOL, newbufsize) + 2 * sizeof(uint32_t)); + int32_t newlen = len + 8; + int32_t newbufsize = newlen + 2 * sizeof(int32_t); + uint8_t *str = (uint8_t *)(dst_alloc(DST_MEMORY_SYMBOL, newbufsize) + 2 * sizeof(int32_t)); dst_string_length(str) = newlen; memcpy(str, buf, len); str[len] = '-'; diff --git a/core/syscalls.c b/core/syscalls.c index ae76e3ba..e866ad45 100644 --- a/core/syscalls.c +++ b/core/syscalls.c @@ -24,10 +24,10 @@ #include #include -int dst_sys_print(DstValue *argv, uint32_t argn) { - uint32_t i; +int dst_sys_print(DstValue *argv, int32_t argn) { + int32_t i; for (i = 0; i < argn; ++i) { - uint32_t j, len; + int32_t j, len; const uint8_t *vstr = dst_to_string(argv[i]); len = dst_string_length(vstr); for (j = 0; j < len; ++j) { @@ -38,7 +38,7 @@ int dst_sys_print(DstValue *argv, uint32_t argn) { return 0; } -int dst_sys_asm(DstValue *argv, uint32_t argn) { +int dst_sys_asm(DstValue *argv, int32_t argn) { DstAssembleOptions opts; DstAssembleResult res; 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)); 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); array->count = argn; memcpy(array->data, argv, argn * sizeof(DstValue)); @@ -71,8 +71,8 @@ int dst_sys_array(DstValue *argv, uint32_t argn) { return 0; } -int dst_sys_table(DstValue *argv, uint32_t argn) { - uint32_t i; +int dst_sys_table(DstValue *argv, int32_t argn) { + int32_t i; DstTable *table = dst_table(argn/2); if (argn & 1) { 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; } -int dst_sys_struct(DstValue *argv, uint32_t argn) { - uint32_t i; +int dst_sys_struct(DstValue *argv, int32_t argn) { + int32_t i; DstValue *st = dst_struct_begin(argn/2); if (argn & 1) { 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; } -int dst_sys_get(DstValue *argv, uint32_t argn) { - uint32_t i; +int dst_sys_get(DstValue *argv, int32_t argn) { + int32_t i; DstValue ds; if (argn < 1) { 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; } -int dst_sys_put(DstValue *argv, uint32_t argn) { +int dst_sys_put(DstValue *argv, int32_t argn) { DstValue ds, key, value; if (argn < 3) { dst_vm_fiber->ret = dst_cstringv("expected at least 3 arguments"); diff --git a/core/table.c b/core/table.c index 33ec9982..369aa506 100644 --- a/core/table.c +++ b/core/table.c @@ -23,7 +23,7 @@ #include /* Initialize a table */ -DstTable *dst_table_init(DstTable *table, uint32_t capacity) { +DstTable *dst_table_init(DstTable *table, int32_t capacity) { DstValue *data; if (capacity < 2) capacity = 2; data = calloc(sizeof(DstValue), capacity); @@ -43,7 +43,7 @@ void dst_table_deinit(DstTable *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)); 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 * bucket where key should go if not in the table. */ static DstValue *dst_table_find(DstTable *t, DstValue key) { - uint32_t index = (dst_hash(key) % (t->capacity / 2)) * 2; - uint32_t i, j; - uint32_t start[2], end[2]; + int32_t index = (dst_hash(key) % t->capacity) & (~1); + int32_t i, j; + int32_t start[2], end[2]; start[0] = index; end[0] = t->capacity; start[1] = 0; end[1] = index; for (j = 0; j < 2; ++j) { for (i = start[j]; i < end[j]; i += 2) { - if (t->data[i].type == DST_NIL) { - if (t->data[i + 1].type == DST_NIL) { + if (dst_checktype(t->data[i], DST_NIL)) { + if (dst_checktype(t->data[i + 1], DST_NIL)) { /* Empty */ return t->data + i; } @@ -72,19 +72,19 @@ static DstValue *dst_table_find(DstTable *t, DstValue key) { } /* 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 *newdata = calloc(sizeof(DstValue), size); if (NULL == newdata) { DST_OUT_OF_MEMORY; } - uint32_t i, oldcapacity; + int32_t i, oldcapacity; oldcapacity = t->capacity; t->data = newdata; t->capacity = size; t->deleted = 0; 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]); bucket[0] = olddata[i]; 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 */ DstValue dst_table_get(DstTable *t, DstValue 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]; else return dst_wrap_nil(); @@ -106,12 +106,12 @@ DstValue dst_table_get(DstTable *t, DstValue key) { * was removed. */ DstValue dst_table_remove(DstTable *t, DstValue 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]; t->count--; t->deleted++; - bucket[0].type = DST_NIL; - bucket[1].type = DST_BOOLEAN; + bucket[0] = dst_wrap_nil(); + bucket[1] = dst_wrap_false(); return ret; } else { return dst_wrap_nil(); @@ -120,19 +120,19 @@ DstValue dst_table_remove(DstTable *t, DstValue key) { /* Put a value into the object */ void dst_table_put(DstTable *t, DstValue key, DstValue value) { - if (key.type == DST_NIL) return; - if (value.type == DST_NIL) { + if (dst_checktype(key, DST_NIL)) return; + if (dst_checktype(value, DST_NIL)) { dst_table_remove(t, key); } else { 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; } 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); } bucket = dst_table_find(t, key); - if (bucket[1].type == DST_BOOLEAN) + if (dst_checktype(bucket[1], DST_FALSE)) --t->deleted; bucket[0] = key; bucket[1] = value; @@ -143,11 +143,9 @@ void dst_table_put(DstTable *t, DstValue key, DstValue value) { /* Clear a table */ void dst_table_clear(DstTable *t) { - uint32_t capacity = t->capacity; - uint32_t i; + int32_t capacity = t->capacity; DstValue *data = t->data; - for (i = 0; i < capacity; i += 2) - data[i].type = DST_NIL; + dst_memempty(data, capacity); t->count = 0; t->deleted = 0; } @@ -156,16 +154,16 @@ void dst_table_clear(DstTable *t) { DstValue dst_table_next(DstTable *t, DstValue key) { const DstValue *bucket, *end; end = t->data + t->capacity; - if (key.type == DST_NIL) { + if (dst_checktype(key, DST_NIL)) { bucket = t->data; } else { 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(); bucket += 2; } for (; bucket < end; bucket += 2) { - if (bucket[0].type != DST_NIL) + if (!dst_checktype(bucket[0], DST_NIL)) return bucket[0]; } return dst_wrap_nil(); @@ -173,10 +171,10 @@ DstValue dst_table_next(DstTable *t, DstValue key) { /* Convert table to struct */ const DstValue *dst_table_to_struct(DstTable *t) { - uint32_t i; + int32_t i; DstValue *st = dst_struct_begin(t->count); 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]); } return dst_struct_end(st); diff --git a/core/tuple.c b/core/tuple.c index 567683cb..468dc0c8 100644 --- a/core/tuple.c +++ b/core/tuple.c @@ -26,9 +26,9 @@ /* 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 * dst_tuple_end is called. */ -DstValue *dst_tuple_begin(uint32_t length) { - char *data = dst_alloc(DST_MEMORY_TUPLE, 2 * sizeof(uint32_t) + length * sizeof(DstValue)); - DstValue *tuple = (DstValue *)(data + (2 * sizeof(uint32_t))); +DstValue *dst_tuple_begin(int32_t length) { + char *data = dst_alloc(DST_MEMORY_TUPLE, 2 * sizeof(int32_t) + length * sizeof(DstValue)); + DstValue *tuple = (DstValue *)(data + (2 * sizeof(int32_t))); dst_tuple_length(tuple) = length; dst_tuple_hash(tuple) = 0; return tuple; @@ -40,7 +40,7 @@ const DstValue *dst_tuple_end(DstValue *tuple) { } /* 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); memcpy(t, values, sizeof(DstValue) * n); 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 */ int dst_tuple_equal(const DstValue *lhs, const DstValue *rhs) { - uint32_t index; - uint32_t llen = dst_tuple_length(lhs); - uint32_t rlen = dst_tuple_length(rhs); - uint32_t lhash = dst_tuple_hash(lhs); - uint32_t rhash = dst_tuple_hash(rhs); + int32_t index; + int32_t llen = dst_tuple_length(lhs); + int32_t rlen = dst_tuple_length(rhs); + int32_t lhash = dst_tuple_hash(lhs); + int32_t rhash = dst_tuple_hash(rhs); if (llen != rlen) return 0; if (lhash == 0) @@ -70,10 +70,10 @@ int dst_tuple_equal(const DstValue *lhs, const DstValue *rhs) { /* Compare tuples */ int dst_tuple_compare(const DstValue *lhs, const DstValue *rhs) { - uint32_t i; - uint32_t llen = dst_tuple_length(lhs); - uint32_t rlen = dst_tuple_length(rhs); - uint32_t count = llen < rlen ? llen : rlen; + int32_t i; + int32_t llen = dst_tuple_length(lhs); + int32_t rlen = dst_tuple_length(rhs); + int32_t count = llen < rlen ? llen : rlen; for (i = 0; i < count; ++i) { int comp = dst_compare(lhs[i], rhs[i]); if (comp != 0) return comp; diff --git a/core/userdata.c b/core/userdata.c index ca7e5cda..ae8e164f 100644 --- a/core/userdata.c +++ b/core/userdata.c @@ -23,7 +23,7 @@ #include /* 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); DstUserdataHeader *header = (DstUserdataHeader *)data; void *user = data + sizeof(DstUserdataHeader); diff --git a/core/util.c b/core/util.c index b85dfb4f..d03bd160 100644 --- a/core/util.c +++ b/core/util.c @@ -50,48 +50,48 @@ const char *dst_type_names[15] = { }; /* 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; uint32_t hash = 5381; while (array < end) hash = (hash << 5) + hash + dst_hash(*array++); - return hash; + return (int32_t) hash; } /* 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; uint32_t hash = 5381; while (str < end) 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. */ -int dst_seq_view(DstValue seq, const DstValue **data, uint32_t *len) { - if (seq.type == DST_ARRAY) { - *data = seq.as.array->data; - *len = seq.as.array->count; +int dst_seq_view(DstValue seq, const DstValue **data, int32_t *len) { + if (dst_checktype(seq, DST_ARRAY)) { + *data = dst_unwrap_array(seq)->data; + *len = dst_unwrap_array(seq)->count; return 1; - } else if (seq.type == DST_TUPLE) { - *data = seq.as.st; - *len = dst_tuple_length(seq.as.st); + } else if (dst_checktype(seq, DST_TUPLE)) { + *data = dst_unwrap_struct(seq); + *len = dst_tuple_length(dst_unwrap_struct(seq)); return 1; } 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. */ -int dst_chararray_view(DstValue str, const uint8_t **data, uint32_t *len) { - if (str.type == DST_STRING || str.type == DST_SYMBOL) { - *data = str.as.string; - *len = dst_string_length(str.as.string); +int dst_chararray_view(DstValue str, const uint8_t **data, int32_t *len) { + if (dst_checktype(str, DST_STRING) || dst_checktype(str, DST_SYMBOL)) { + *data = dst_unwrap_string(str); + *len = dst_string_length(dst_unwrap_string(str)); return 1; - } else if (str.type == DST_BUFFER) { - *data = str.as.buffer->data; - *len = str.as.buffer->count; + } else if (dst_checktype(str, DST_BUFFER)) { + *data = dst_unwrap_buffer(str)->data; + *len = dst_unwrap_buffer(str)->count; return 1; } 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 * identical structure. Returns 1 if the view can be constructed and * 0 if the type is invalid. */ -int dst_hashtable_view(DstValue tab, const DstValue **data, uint32_t *len, uint32_t *cap) { - if (tab.type == DST_TABLE) { - *data = tab.as.table->data; - *cap = tab.as.table->capacity; - *len = tab.as.table->count; +int dst_hashtable_view(DstValue tab, const DstValue **data, int32_t *len, int32_t *cap) { + if (dst_checktype(tab, DST_TABLE)) { + *data = dst_unwrap_table(tab)->data; + *cap = dst_unwrap_table(tab)->capacity; + *len = dst_unwrap_table(tab)->count; return 1; - } else if (tab.type == DST_STRUCT) { - *data = tab.as.st; - *cap = dst_struct_capacity(tab.as.st); - *len = dst_struct_length(tab.as.st); + } else if (dst_checktype(tab, DST_STRUCT)) { + *data = dst_unwrap_struct(tab); + *cap = dst_struct_capacity(dst_unwrap_struct(tab)); + *len = dst_struct_length(dst_unwrap_struct(tab)); return 1; } 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; -} diff --git a/core/value.c b/core/value.c index 665e7870..8f850c37 100644 --- a/core/value.c +++ b/core/value.c @@ -26,39 +26,33 @@ * 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. */ int dst_equals(DstValue x, DstValue y) { int result = 0; - if (x.type != y.type) { + if (dst_type(x) != dst_type(y)) { result = 0; } else { - switch (x.type) { + switch (dst_type(x)) { case DST_NIL: + case DST_TRUE: + case DST_FALSE: result = 1; break; - case DST_BOOLEAN: - result = (x.as.boolean == y.as.boolean); - break; case DST_REAL: - result = (x.as.real == y.as.real); + result = (dst_unwrap_real(x) == dst_unwrap_real(y)); break; case DST_INTEGER: - result = (x.as.integer == y.as.integer); + result = (dst_unwrap_integer(x) == dst_unwrap_integer(y)); break; 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; 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; default: /* compare pointers */ - result = (x.as.pointer == y.as.pointer); + result = (dst_unwrap_pointer(x) == dst_unwrap_pointer(y)); break; } } @@ -66,41 +60,40 @@ int dst_equals(DstValue x, DstValue y) { } /* Computes a hash value for a function */ -uint32_t dst_hash(DstValue x) { - uint32_t hash = 0; - switch (x.type) { +int32_t dst_hash(DstValue x) { + int32_t hash = 0; + switch (dst_type(x)) { case DST_NIL: - hash = 0; - break; - case DST_BOOLEAN: - hash = x.as.boolean; + case DST_FALSE: + case DST_TRUE: + hash = dst_type(x); break; case DST_STRING: case DST_SYMBOL: - hash = dst_string_hash(x.as.string); + hash = dst_string_hash(dst_unwrap_string(x)); break; case DST_TUPLE: - if (0 == dst_tuple_hash(x.as.tuple)) - hash = dst_tuple_hash(x.as.tuple) = - dst_array_calchash(x.as.tuple, dst_tuple_length(x.as.tuple)); + if (0 == dst_tuple_hash(dst_unwrap_tuple(x))) + hash = dst_tuple_hash(dst_unwrap_tuple(x)) = + dst_array_calchash(dst_unwrap_tuple(x), dst_tuple_length(dst_unwrap_tuple(x))); else - hash = dst_tuple_hash(x.as.tuple); + hash = dst_tuple_hash(dst_unwrap_tuple(x)); break; case DST_STRUCT: - if (0 == dst_struct_hash(x.as.st)) - hash = dst_struct_hash(x.as.st) = - dst_array_calchash(x.as.st, dst_struct_capacity(x.as.st)); + if (0 == dst_struct_hash(dst_unwrap_struct(x))) + hash = dst_struct_hash(dst_unwrap_struct(x)) = + dst_array_calchash(dst_unwrap_struct(x), dst_struct_capacity(dst_unwrap_struct(x))); else - hash = dst_struct_hash(x.as.st); + hash = dst_struct_hash(dst_unwrap_struct(x)); break; default: if (sizeof(double) == sizeof(void *)) { /* Assuming 8 byte pointer */ - uint64_t i = x.as.integer; - hash = (uint32_t)(i >> 32) ^ (uint32_t)(i & 0xFFFFFFFF); + uint64_t i = dst_u64(x); + hash = (int32_t)(i >> 32) ^ (int32_t)(i & 0xFFFFFFFF); } else { /* Assuming 4 byte pointer (or smaller) */ - hash = (uint32_t) (x.as.pointer - NULL); + hash = (int32_t) (dst_unwrap_pointer(x) - NULL); } break; } @@ -111,51 +104,47 @@ uint32_t dst_hash(DstValue x) { * If y is less, returns 1. All types are comparable * and should have strict ordering. */ int dst_compare(DstValue x, DstValue y) { - if (x.type == y.type) { - switch (x.type) { + if (dst_type(x) == dst_type(y)) { + switch (dst_type(x)) { case DST_NIL: + case DST_FALSE: + case DST_TRUE: return 0; - case DST_BOOLEAN: - if (x.as.boolean == y.as.boolean) { - return 0; - } else { - return x.as.boolean ? 1 : -1; - } case DST_REAL: /* Check for nans to ensure total order */ - if (x.as.real != x.as.real) - return y.as.real != y.as.real + if (dst_unwrap_real(x) != dst_unwrap_real(x)) + return dst_unwrap_real(y) != dst_unwrap_real(y) ? 0 : -1; - if (y.as.real != y.as.real) + if (dst_unwrap_real(y) != dst_unwrap_real(y)) return 1; - if (x.as.real == y.as.real) { + if (dst_unwrap_real(x) == dst_unwrap_real(y)) { return 0; } else { - return x.as.real > y.as.real ? 1 : -1; + return dst_unwrap_real(x) > dst_unwrap_real(y) ? 1 : -1; } case DST_INTEGER: - if (x.as.integer == y.as.integer) { + if (dst_unwrap_integer(x) == dst_unwrap_integer(y)) { return 0; } else { - return x.as.integer > y.as.integer ? 1 : -1; + return dst_unwrap_integer(x) > dst_unwrap_integer(y) ? 1 : -1; } 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: - 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: - return dst_struct_compare(x.as.st, y.as.st); + return dst_struct_compare(dst_unwrap_struct(x), dst_unwrap_struct(y)); default: - if (x.as.string == y.as.string) { + if (dst_unwrap_string(x) == dst_unwrap_string(y)) { return 0; } 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; @@ -164,36 +153,36 @@ int dst_compare(DstValue x, DstValue y) { /* Get a value out af an associated data structure. For invalid * data structure or invalid key, returns nil. */ DstValue dst_get(DstValue ds, DstValue key) { - switch (ds.type) { + switch (dst_type(ds)) { case DST_ARRAY: - if (key.type == DST_INTEGER && - key.as.integer >= 0 && - key.as.integer < ds.as.array->count) - return ds.as.array->data[key.as.integer]; + if (dst_checktype(key, DST_INTEGER) && + dst_unwrap_integer(key) >= 0 && + dst_unwrap_integer(key) < dst_unwrap_array(ds)->count) + return dst_unwrap_array(ds)->data[dst_unwrap_integer(key)]; break; case DST_TUPLE: - if (key.type == DST_INTEGER && - key.as.integer >= 0 && - key.as.integer < dst_tuple_length(ds.as.tuple)) - return ds.as.tuple[key.as.integer]; + if (dst_checktype(key, DST_INTEGER) && + dst_unwrap_integer(key) >= 0 && + dst_unwrap_integer(key) < dst_tuple_length(dst_unwrap_tuple(ds))) + return dst_unwrap_tuple(ds)[dst_unwrap_integer(key)]; break; case DST_BUFFER: - if (key.type == DST_INTEGER && - key.as.integer >= 0 && - key.as.integer < ds.as.buffer->count) - return dst_wrap_integer(ds.as.buffer->data[key.as.integer]); + if (dst_checktype(key, DST_INTEGER) && + dst_unwrap_integer(key) >= 0 && + dst_unwrap_integer(key) < dst_unwrap_buffer(ds)->count) + return dst_wrap_integer(dst_unwrap_buffer(ds)->data[dst_unwrap_integer(key)]); break; case DST_STRING: case DST_SYMBOL: - if (key.type == DST_INTEGER && - key.as.integer >= 0 && - key.as.integer < dst_string_length(ds.as.string)) - return dst_wrap_integer(ds.as.string[key.as.integer]); + if (dst_checktype(key, DST_INTEGER) && + dst_unwrap_integer(key) >= 0 && + dst_unwrap_integer(key) < dst_string_length(dst_unwrap_string(ds))) + return dst_wrap_integer(dst_unwrap_string(ds)[dst_unwrap_integer(key)]); break; case DST_STRUCT: - return dst_struct_get(ds.as.st, key); + return dst_struct_get(dst_unwrap_struct(ds), key); case DST_TABLE: - return dst_table_get(ds.as.table, key); + return dst_table_get(dst_unwrap_table(ds), key); default: break; } @@ -203,22 +192,22 @@ DstValue dst_get(DstValue ds, DstValue key) { /* Set a value in an associative data structure. Returns possible * error message, and NULL if no error. */ void dst_put(DstValue ds, DstValue key, DstValue value) { - switch (ds.type) { + switch (dst_type(ds)) { case DST_ARRAY: - if (key.type == DST_INTEGER && - key.as.integer >= 0 && - key.as.integer < ds.as.array->count) - ds.as.array->data[key.as.integer] = value; + if (dst_checktype(key, DST_INTEGER) && + dst_unwrap_integer(key) >= 0 && + dst_unwrap_integer(key) < dst_unwrap_array(ds)->count) + dst_unwrap_array(ds)->data[dst_unwrap_integer(key)] = value; return; case DST_BUFFER: - if (key.type == DST_INTEGER && - value.type == DST_INTEGER && - key.as.integer >= 0 && - key.as.integer < ds.as.buffer->count) - ds.as.buffer->data[key.as.integer] = value.as.integer; + if (dst_checktype(key, DST_INTEGER) && + dst_checktype(value, DST_INTEGER) && + dst_unwrap_integer(key) >= 0 && + dst_unwrap_integer(key) < dst_unwrap_buffer(ds)->count) + dst_unwrap_buffer(ds)->data[dst_unwrap_integer(key)] = dst_unwrap_integer(value); return; case DST_TABLE: - dst_table_put(ds.as.table, key, value); + dst_table_put(dst_unwrap_table(ds), key, value); return; default: 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 * associative data structure. */ DstValue dst_next(DstValue ds, DstValue key) { - switch(ds.type) { + switch(dst_type(ds)) { default: return dst_wrap_nil(); case DST_TABLE: - return dst_table_next(ds.as.table, key); + return dst_table_next(dst_unwrap_table(ds), key); 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 */ -uint32_t dst_length(DstValue x) { - switch (x.type) { +int32_t dst_length(DstValue x) { + switch (dst_type(x)) { default: return 0; case DST_STRING: - return dst_string_length(x.as.string); + return dst_string_length(dst_unwrap_string(x)); case DST_ARRAY: - return x.as.array->count; + return dst_unwrap_array(x)->count; case DST_BUFFER: - return x.as.buffer->count; + return dst_unwrap_buffer(x)->count; case DST_TUPLE: - return dst_tuple_length(x.as.tuple); + return dst_tuple_length(dst_unwrap_tuple(x)); case DST_STRUCT: - return dst_struct_length(x.as.st); + return dst_struct_length(dst_unwrap_struct(x)); 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 */ -uint32_t dst_capacity(DstValue x) { - switch (x.type) { +int32_t dst_capacity(DstValue x) { + switch (dst_type(x)) { default: return 0; case DST_STRING: - return dst_string_length(x.as.string); + return dst_string_length(dst_unwrap_string(x)); case DST_ARRAY: - return x.as.array->capacity; + return dst_unwrap_array(x)->capacity; case DST_BUFFER: - return x.as.buffer->capacity; + return dst_unwrap_buffer(x)->capacity; case DST_TUPLE: - return dst_tuple_length(x.as.tuple); + return dst_tuple_length(dst_unwrap_tuple(x)); case DST_STRUCT: - return dst_struct_length(x.as.st); + return dst_struct_length(dst_unwrap_struct(x)); 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 */ -DstValue dst_getindex(DstValue ds, uint32_t index) { - switch (ds.type) { +DstValue dst_getindex(DstValue ds, int32_t index) { + switch (dst_type(ds)) { default: return dst_wrap_nil(); case DST_STRING: - if (index >= dst_string_length(ds.as.string)) return dst_wrap_nil(); - return dst_wrap_integer(ds.as.string[index]); + if (index >= dst_string_length(dst_unwrap_string(ds))) return dst_wrap_nil(); + return dst_wrap_integer(dst_unwrap_string(ds)[index]); case DST_ARRAY: - if (index >= ds.as.array->count) return dst_wrap_nil(); - return ds.as.array->data[index]; + if (index >= dst_unwrap_array(ds)->count) return dst_wrap_nil(); + return dst_unwrap_array(ds)->data[index]; case DST_BUFFER: - if (index >= ds.as.buffer->count) return dst_wrap_nil(); - return dst_wrap_integer(ds.as.buffer->data[index]); + if (index >= dst_unwrap_buffer(ds)->count) return dst_wrap_nil(); + return dst_wrap_integer(dst_unwrap_buffer(ds)->data[index]); case DST_TUPLE: - if (index >= dst_tuple_length(ds.as.tuple)) return dst_wrap_nil(); - return ds.as.tuple[index]; + if (index >= dst_tuple_length(dst_unwrap_tuple(ds))) return dst_wrap_nil(); + return dst_unwrap_tuple(ds)[index]; } } /* Set an index in a linear data structure. Does nothing if data structure * is invalid */ -void dst_setindex(DstValue ds, DstValue value, uint32_t index) { - switch (ds.type) { +void dst_setindex(DstValue ds, DstValue value, int32_t index) { + switch (dst_type(ds)) { default: return; case DST_ARRAY: - if (index >= ds.as.array->count) { - dst_array_ensure(ds.as.array, 2 * index); - ds.as.array->count = index + 1; + if (index >= dst_unwrap_array(ds)->count) { + dst_array_ensure(dst_unwrap_array(ds), 2 * index); + dst_unwrap_array(ds)->count = index + 1; } - ds.as.array->data[index] = value; + dst_unwrap_array(ds)->data[index] = value; return; case DST_BUFFER: - if (value.type != DST_INTEGER) return; - if (index >= ds.as.buffer->count) { - dst_buffer_ensure(ds.as.buffer, 2 * index); - ds.as.buffer->count = index + 1; + if (!dst_checktype(value, DST_INTEGER)) return; + if (index >= dst_unwrap_buffer(ds)->count) { + dst_buffer_ensure(dst_unwrap_buffer(ds), 2 * index); + 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; } } diff --git a/core/vm.c b/core/vm.c index b6dac379..ba310dba 100644 --- a/core/vm.c +++ b/core/vm.c @@ -67,26 +67,26 @@ int dst_continue() { * Pulls out unsigned integers */ #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_binop_integer(op) \ 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++;\ vm_next(); #define vm_binop_real(op)\ 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++;\ vm_next(); #define vm_binop_immediate(op)\ 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++;\ vm_next(); @@ -95,15 +95,15 @@ int dst_continue() { {\ DstValue op1 = stack[oparg(2, 0xFF)];\ DstValue op2 = stack[oparg(3, 0xFF)];\ - vm_assert(op1.type == DST_INTEGER || op1.type == DST_REAL, "expected number");\ - vm_assert(op2.type == DST_INTEGER || op2.type == DST_REAL, "expected number");\ - stack[oparg(1, 0xFF)] = op1.type == DST_INTEGER\ - ? (op2.type == DST_INTEGER\ - ? dst_wrap_integer(op1.as.integer op op2.as.integer)\ - : dst_wrap_real(dst_integer_to_real(op1.as.integer) op op2.as.real))\ - : (op2.type == DST_INTEGER\ - ? dst_wrap_real(op1.as.real op dst_integer_to_real(op2.as.integer))\ - : dst_wrap_real(op1.as.real op op2.as.real));\ + vm_assert(dst_checktype(op1, DST_INTEGER) || dst_checktype(op1, DST_REAL), "expected number");\ + vm_assert(dst_checktype(op2, DST_INTEGER) || dst_checktype(op2, DST_REAL), "expected number");\ + stack[oparg(1, 0xFF)] = dst_checktype(op1, DST_INTEGER)\ + ? (dst_checktype(op2, DST_INTEGER)\ + ? dst_wrap_integer(dst_unwrap_integer(op1) op dst_unwrap_integer(op2))\ + : dst_wrap_real((double)dst_unwrap_integer(op1) op dst_unwrap_real(op2)))\ + : (dst_checktype(op2, DST_INTEGER)\ + ? dst_wrap_real(dst_unwrap_real(op1) op (double)dst_unwrap_integer(op2))\ + : dst_wrap_real(dst_unwrap_real(op1) op dst_unwrap_real(op2)));\ pc++;\ vm_next();\ } @@ -137,7 +137,7 @@ int dst_continue() { goto vm_error; 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"); pc++; vm_next(); @@ -147,7 +147,7 @@ int dst_continue() { goto vm_return; case DOP_RETURN_NIL: - dst_vm_fiber->ret.type = DST_NIL; + dst_vm_fiber->ret = dst_wrap_nil(); goto vm_return; case DOP_ADD_INTEGER: @@ -184,16 +184,16 @@ int dst_continue() { vm_binop(*); case DOP_DIVIDE_INTEGER: - vm_assert(stack[oparg(3, 0xFF)].as.integer != 0, "integer divide by zero"); - vm_assert(!(stack[oparg(3, 0xFF)].as.integer == -1 && - stack[oparg(2, 0xFF)].as.integer == DST_INTEGER_MIN), + vm_assert(dst_unwrap_integer(stack[oparg(3, 0xFF)]) != 0, "integer divide by zero"); + vm_assert(!(dst_unwrap_integer(stack[oparg(3, 0xFF)]) == -1 && + dst_unwrap_integer(stack[oparg(2, 0xFF)]) == DST_INTEGER_MIN), "integer divide overflow"); vm_binop_integer(/); case DOP_DIVIDE_IMMEDIATE: { - int64_t op1 = stack[oparg(2, 0xFF)].as.integer; - int64_t op2 = *((int32_t *)pc) >> 24; + int32_t op1 = dst_unwrap_integer(stack[oparg(2, 0xFF)]); + int32_t op2 = *((int32_t *)pc) >> 24; /* Check for degenerate integer division (divide by zero, and dividing * min value by -1). These checks could be omitted if the arg is not * 0 or -1. */ @@ -214,20 +214,20 @@ int dst_continue() { { DstValue op1 = stack[oparg(2, 0xFF)]; DstValue op2 = stack[oparg(3, 0xFF)]; - vm_assert(op1.type == DST_INTEGER || op1.type == DST_REAL, "expected number"); - vm_assert(op2.type == DST_INTEGER || op2.type == DST_REAL, "expected number"); - if (op2.type == DST_INTEGER && op2.as.integer == 0) + vm_assert(dst_checktype(op1, DST_INTEGER) || dst_checktype(op1, DST_REAL), "expected number"); + vm_assert(dst_checktype(op2, DST_INTEGER) || dst_checktype(op2, DST_REAL), "expected number"); + if (dst_checktype(op2, DST_INTEGER) && dst_unwrap_integer(op2) == 0) op2 = dst_wrap_real(0.0); - if (op2.type == DST_INTEGER && op2.as.integer == -1 && - op1.type == DST_INTEGER && op1.as.integer == DST_INTEGER_MIN) - op2 = dst_wrap_real(-1); - stack[oparg(1, 0xFF)] = op1.type == DST_INTEGER - ? op2.type == DST_INTEGER - ? dst_wrap_integer(op1.as.integer / op2.as.integer) - : dst_wrap_real(dst_integer_to_real(op1.as.integer) / op2.as.real) - : op2.type == DST_INTEGER - ? dst_wrap_real(op1.as.real / dst_integer_to_real(op2.as.integer)) - : dst_wrap_real(op1.as.real / op2.as.real); + if (dst_checktype(op2, DST_INTEGER) && dst_unwrap_integer(op2) == -1 && + dst_checktype(op1, DST_INTEGER) && dst_unwrap_integer(op1) == DST_INTEGER_MIN) + op2 = dst_wrap_real(-1.0); + stack[oparg(1, 0xFF)] = dst_checktype(op1, DST_INTEGER) + ? (dst_checktype(op2, DST_INTEGER) + ? dst_wrap_integer(dst_unwrap_integer(op1) / dst_unwrap_integer(op2)) + : dst_wrap_real((double)dst_unwrap_integer(op1) / dst_unwrap_real(op2))) + : (dst_checktype(op2, DST_INTEGER) + ? dst_wrap_real(dst_unwrap_real(op1) / (double)dst_unwrap_integer(op2)) + : dst_wrap_real(dst_unwrap_real(op1) / dst_unwrap_real(op2))); pc++; vm_next(); } @@ -242,21 +242,21 @@ int dst_continue() { vm_binop_integer(^); 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(); case DOP_SHIFT_RIGHT_UNSIGNED: 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++; vm_next(); case DOP_SHIFT_RIGHT_UNSIGNED_IMMEDIATE: 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++; vm_next(); @@ -266,7 +266,7 @@ int dst_continue() { case DOP_SHIFT_RIGHT_IMMEDIATE: 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++; vm_next(); @@ -276,7 +276,7 @@ int dst_continue() { case DOP_SHIFT_LEFT_IMMEDIATE: 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++; vm_next(); @@ -307,43 +307,39 @@ int dst_continue() { vm_next(); case DOP_LESS_THAN: - stack[oparg(1, 0xFF)].type = DST_BOOLEAN; - stack[oparg(1, 0xFF)].as.boolean = dst_compare( + stack[oparg(1, 0xFF)] = dst_wrap_boolean(dst_compare( stack[oparg(2, 0xFF)], stack[oparg(3, 0xFF)] - ) < 0; + ) < 0); pc++; vm_next(); case DOP_GREATER_THAN: - stack[oparg(1, 0xFF)].type = DST_BOOLEAN; - stack[oparg(1, 0xFF)].as.boolean = dst_compare( + stack[oparg(1, 0xFF)] = dst_wrap_boolean(dst_compare( stack[oparg(2, 0xFF)], stack[oparg(3, 0xFF)] - ) > 0; + ) > 0); pc++; vm_next(); case DOP_EQUALS: - stack[oparg(1, 0xFF)].type = DST_BOOLEAN; - stack[oparg(1, 0xFF)].as.boolean = dst_equals( + stack[oparg(1, 0xFF)] = dst_wrap_boolean(dst_equals( stack[oparg(2, 0xFF)], stack[oparg(3, 0xFF)] - ); + )); pc++; vm_next(); case DOP_COMPARE: - stack[oparg(1, 0xFF)].type = DST_INTEGER; - stack[oparg(1, 0xFF)].as.integer = dst_compare( - stack[oparg(2, 0xFF)], - stack[oparg(3, 0xFF)] - ); + stack[oparg(1, 0xFF)] = dst_wrap_integer(dst_compare( + stack[oparg(2, 0xFF)], + stack[oparg(3, 0xFF)] + )); pc++; vm_next(); case DOP_LOAD_NIL: - stack[oparg(1, 0xFFFFFF)].type = DST_NIL; + stack[oparg(1, 0xFFFFFF)] = dst_wrap_nil(); pc++; vm_next(); @@ -358,15 +354,15 @@ int dst_continue() { vm_next(); case DOP_LOAD_CONSTANT: - vm_assert(oparg(2, 0xFFFF) < func->def->constants_length, "invalid constant"); - stack[oparg(1, 0xFF)] = func->def->constants[oparg(2, 0xFFFF)]; + vm_assert((int32_t)oparg(2, 0xFFFF) < func->def->constants_length, "invalid constant"); + stack[oparg(1, 0xFF)] = func->def->constants[(int32_t)oparg(2, 0xFFFF)]; pc++; vm_next(); case DOP_LOAD_UPVALUE: { - uint32_t eindex = oparg(2, 0xFF); - uint32_t vindex = oparg(3, 0xFF); + int32_t eindex = oparg(2, 0xFF); + int32_t vindex = oparg(3, 0xFF); DstFuncEnv *env; vm_assert(func->def->environments_length > eindex, "invalid upvalue"); env = func->envs[eindex]; @@ -384,8 +380,8 @@ int dst_continue() { case DOP_SET_UPVALUE: { - uint32_t eindex = oparg(2, 0xFF); - uint32_t vindex = oparg(3, 0xFF); + int32_t eindex = oparg(2, 0xFF); + int32_t vindex = oparg(3, 0xFF); DstFuncEnv *env; vm_assert(func->def->environments_length > eindex, "invalid upvalue"); env = func->envs[eindex]; @@ -401,12 +397,12 @@ int dst_continue() { case DOP_CLOSURE: { - uint32_t i; + int32_t i; DstFunction *fn; DstFuncDef *fd; - vm_assert(oparg(2, 0xFFFF) < func->def->constants_length, "invalid constant"); - vm_assert(func->def->constants[oparg(2, 0xFFFF)].type == DST_NIL, "constant must be funcdef"); - fd = (DstFuncDef *)(func->def->constants[oparg(2, 0xFFFF)].as.pointer); + vm_assert((int32_t)oparg(2, 0xFFFF) < func->def->constants_length, "invalid constant"); + vm_assert(dst_checktype(func->def->constants[oparg(2, 0xFFFF)], DST_NIL), "constant must be funcdef"); + fd = (DstFuncDef *)(dst_unwrap_pointer(func->def->constants[(int32_t)oparg(2, 0xFFFF)])); fn = dst_alloc(DST_MEMORY_FUNCTION, sizeof(DstFunction)); fn->envs = malloc(sizeof(DstFuncEnv *) * fd->environments_length); if (NULL == fn->envs) { @@ -423,7 +419,7 @@ int dst_continue() { fn->envs[0] = NULL; } 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]; } stack[oparg(1, 0xFF)] = dst_wrap_function(fn); @@ -453,7 +449,7 @@ int dst_continue() { case DOP_PUSH_ARRAY: { - uint32_t count; + int32_t count; const DstValue *array; if (dst_seq_view(stack[oparg(1, 0xFFFFFF)], &array, &count)) { dst_fiber_pushn(dst_vm_fiber, array, count); @@ -467,16 +463,16 @@ int dst_continue() { case DOP_CALL: { DstValue callee = stack[oparg(2, 0xFFFF)]; - if (callee.type == DST_FUNCTION) { - func = callee.as.function; + if (dst_checktype(callee, DST_FUNCTION)) { + func = dst_unwrap_function(callee); dst_fiber_funcframe(dst_vm_fiber, func); stack = dst_vm_fiber->data + dst_vm_fiber->frame; pc = func->def->bytecode; vm_checkgc_next(); - } else if (callee.type == DST_CFUNCTION) { + } else if (dst_checktype(callee, DST_CFUNCTION)) { dst_fiber_cframe(dst_vm_fiber); - dst_vm_fiber->ret.type = DST_NIL; - if (callee.as.cfunction( + dst_vm_fiber->ret = dst_wrap_nil(); + if (dst_unwrap_cfunction(callee)( dst_vm_fiber->data + dst_vm_fiber->frame, dst_vm_fiber->frametop - dst_vm_fiber->frame)) { goto vm_error; @@ -489,16 +485,16 @@ int dst_continue() { case DOP_TAILCALL: { DstValue callee = stack[oparg(2, 0xFFFF)]; - if (callee.type == DST_FUNCTION) { - func = callee.as.function; + if (dst_checktype(callee, DST_FUNCTION)) { + func = dst_unwrap_function(callee); dst_fiber_funcframe_tail(dst_vm_fiber, func); stack = dst_vm_fiber->data + dst_vm_fiber->frame; pc = func->def->bytecode; vm_checkgc_next(); - } else if (callee.type == DST_CFUNCTION) { + } else if (dst_checktype(callee, DST_CFUNCTION)) { dst_fiber_cframe_tail(dst_vm_fiber); - dst_vm_fiber->ret.type = DST_NIL; - if (callee.as.cfunction( + dst_vm_fiber->ret = dst_wrap_nil(); + if (dst_unwrap_cfunction(callee)( dst_vm_fiber->data + dst_vm_fiber->frame, dst_vm_fiber->frametop - dst_vm_fiber->frame)) { goto vm_error; @@ -513,7 +509,7 @@ int dst_continue() { DstCFunction f = dst_vm_syscalls[oparg(2, 0xFF)]; vm_assert(NULL != f, "invalid syscall"); 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, dst_vm_fiber->frametop - dst_vm_fiber->frame)) { goto vm_error; @@ -536,10 +532,10 @@ int dst_continue() { DstStackFrame *frame = dst_stack_frame(stack); DstValue temp = stack[oparg(2, 0xFF)]; DstValue retvalue = stack[oparg(3, 0xFF)]; - vm_assert(temp.type == DST_FIBER || - temp.type == DST_NIL, "expected fiber"); - nextfiber = temp.type == DST_FIBER - ? temp.as.fiber + vm_assert(dst_checktype(temp, DST_FIBER) || + dst_checktype(temp, DST_NIL), "expected fiber"); + nextfiber = dst_checktype(temp, DST_FIBER) + ? dst_unwrap_fiber(temp) : dst_vm_fiber->parent; /* Check for root fiber */ if (NULL == nextfiber) { @@ -649,15 +645,15 @@ int dst_run(DstValue callee) { } else { 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_fiber_cframe(dst_vm_fiber); - return callee.as.cfunction(dst_vm_fiber->data + dst_vm_fiber->frame, 0); - } else if (callee.type == DST_FUNCTION) { - dst_fiber_funcframe(dst_vm_fiber, callee.as.function); + return dst_unwrap_cfunction(callee)(dst_vm_fiber->data + dst_vm_fiber->frame, 0); + } else if (dst_checktype(callee, DST_FUNCTION)) { + dst_fiber_funcframe(dst_vm_fiber, dst_unwrap_function(callee)); return dst_continue(); } - dst_vm_fiber->ret = dst_wrap_string(dst_cstring("expected function")); + dst_vm_fiber->ret = dst_cstringv("expected function"); return 1; } diff --git a/core/wrap.c b/core/wrap.c index b3facbc0..582c9bf6 100644 --- a/core/wrap.c +++ b/core/wrap.c @@ -22,6 +22,49 @@ #include +#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 * dst value, which can then be used in dst internal functions. Use * these functions sparingly, as these function will let the programmer @@ -34,6 +77,24 @@ DstValue dst_wrap_nil() { 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)\ DstValue dst_wrap_##NAME(TYPE x) {\ DstValue y;\ @@ -43,18 +104,19 @@ DstValue dst_wrap_##NAME(TYPE x) {\ } DST_WRAP_DEFINE(real, double, DST_REAL, real) -DST_WRAP_DEFINE(integer, int64_t, DST_INTEGER, integer) -DST_WRAP_DEFINE(boolean, int, DST_BOOLEAN, boolean) -DST_WRAP_DEFINE(string, const uint8_t *, DST_STRING, string) -DST_WRAP_DEFINE(symbol, const uint8_t *, DST_SYMBOL, string) -DST_WRAP_DEFINE(array, DstArray *, DST_ARRAY, array) -DST_WRAP_DEFINE(tuple, const DstValue *, DST_TUPLE, tuple) -DST_WRAP_DEFINE(struct, const DstValue *, DST_STRUCT, st) -DST_WRAP_DEFINE(thread, DstFiber *, DST_FIBER, fiber) -DST_WRAP_DEFINE(buffer, DstBuffer *, DST_BUFFER, buffer) -DST_WRAP_DEFINE(function, DstFunction *, DST_FUNCTION, function) -DST_WRAP_DEFINE(cfunction, DstCFunction, DST_CFUNCTION, cfunction) -DST_WRAP_DEFINE(table, DstTable *, DST_TABLE, table) +DST_WRAP_DEFINE(integer, int32_t, DST_INTEGER, integer) +DST_WRAP_DEFINE(string, const uint8_t *, DST_STRING, cpointer) +DST_WRAP_DEFINE(symbol, const uint8_t *, DST_SYMBOL, cpointer) +DST_WRAP_DEFINE(array, DstArray *, DST_ARRAY, pointer) +DST_WRAP_DEFINE(tuple, const DstValue *, DST_TUPLE, cpointer) +DST_WRAP_DEFINE(struct, const DstValue *, DST_STRUCT, cpointer) +DST_WRAP_DEFINE(thread, DstFiber *, DST_FIBER, pointer) +DST_WRAP_DEFINE(buffer, DstBuffer *, DST_BUFFER, pointer) +DST_WRAP_DEFINE(function, DstFunction *, DST_FUNCTION, pointer) +DST_WRAP_DEFINE(cfunction, DstCFunction, DST_CFUNCTION, pointer) +DST_WRAP_DEFINE(table, DstTable *, DST_TABLE, pointer) DST_WRAP_DEFINE(userdata, void *, DST_USERDATA, pointer) #undef DST_WRAP_DEFINE + +#endif diff --git a/include/dst/dst.h b/include/dst/dst.h index 0d1f969c..02f047f1 100644 --- a/include/dst/dst.h +++ b/include/dst/dst.h @@ -20,8 +20,8 @@ * IN THE SOFTWARE. */ -#ifndef DST_H_defined -#define DST_H_defined +#ifndef DST_NANBOX_H_defined +#define DST_NANBOX_H_defined #include #include @@ -33,7 +33,7 @@ * From webkit source. */ -/* Unix? */ +/* Check Unix */ #if defined(_AIX) \ || defined(__APPLE__) /* Darwin */ \ || defined(__FreeBSD__) || defined(__DragonFly__) \ @@ -48,12 +48,12 @@ #define DST_UNIX 1 #endif -/* Windows? */ +/* Check Windows */ #if defined(WIN32) || defined(_WIN32) #define DST_WINDOWS 1 #endif -/* 64-bit mode? */ +/* Check 64-bit vs 32-bit */ #if ((defined(__x86_64__) || defined(_M_X64)) \ && (defined(DST_UNIX) || defined(DST_WINDOWS))) \ || (defined(__ia64__) && defined(__LP64__)) /* Itanium in LP64 mode */ \ @@ -67,7 +67,7 @@ #define DST_32 1 #endif -/* Big endian? (Mostly equivallent to how WebKit does it) */ +/* Check big endian */ #if defined(__MIPSEB__) /* MIPS 32-bit */ \ || defined(__ppc__) || defined(__PPC__) /* CPU(PPC) - PowerPC 32-bit */ \ || defined(__powerpc__) || defined(__powerpc) || defined(__POWERPC__) \ @@ -81,6 +81,8 @@ || ((defined(__CC_ARM) || defined(__ARMCC__)) /* ARM RealView compiler */ \ && defined(__BIG_ENDIAN)) #define DST_BIG_ENDIAN 1 +#else +#define DST_LITTLE_ENDIAN 1 #endif /* 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) #endif -#define DST_INTEGER_MIN INT64_MIN -#define DST_INTEGER_MAX INT64_MAX +#define DST_INTEGER_MIN INT32_MIN +#define DST_INTEGER_MAX INT32_MAX /* Prevent some recursive functions from recursing too deeply * ands crashing (the parser). Instead, error out. */ #define DST_RECURSION_GUARD 1000 -/* Names of all of the types */ -extern const char *dst_type_names[15]; - -/* 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 */ +#ifdef DST_NANBOX +typedef union DstValue DstValue; +#else typedef struct DstValue DstValue; +#endif /* All of the dst types */ -typedef int DstBoolean; typedef struct DstFunction DstFunction; typedef struct DstArray DstArray; typedef struct DstBuffer DstBuffer; typedef struct DstTable DstTable; typedef struct DstFiber DstFiber; -typedef int (*DstCFunction)(DstValue *argv, uint32_t argn); /* Other structs */ typedef struct DstUserdataHeader DstUserdataHeader; @@ -143,42 +124,237 @@ typedef struct DstFuncEnv DstFuncEnv; typedef struct DstStackFrame DstStackFrame; typedef union DstValueUnion DstValueUnion; typedef struct DstUserType DstUserType; +typedef int (*DstCFunction)(DstValue *argv, int32_t argn); -/* Union datatype */ -union DstValueUnion { - DstBoolean boolean; - double real; - int64_t integer; - uint64_t uinteger; - DstArray *array; - DstBuffer *buffer; - DstTable *table; - DstFiber *fiber; - const DstValue *tuple; - DstCFunction cfunction; - DstFunction *function; - const DstValue *st; - const uint8_t *string; +/* Names of all of the types */ +extern const char *dst_type_names[15]; + +/* Basic types for all Dst Values */ +typedef enum DstType { + DST_NIL, + DST_FALSE, + DST_TRUE, + DST_FIBER, + DST_INTEGER, + DST_REAL, + DST_STRING, + DST_SYMBOL, + DST_ARRAY, + 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; + double real; }; -/* The general dst value type. Contains a large union and - * the type information of the value */ +/* This representation uses 48 bit pointers. The trade off vs. the LuaJIT style + * 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 { - DstValueUnion as; + union { + uint64_t u64; + double real; + int32_t integer; + void *pointer; + const void *cpointer; + } as; 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 * operating system threads. */ struct DstFiber { DstValue ret; /* Return value */ DstValue *data; DstFiber *parent; - uint32_t frame; /* Index of the stack frame */ - uint32_t frametop; /* Index of top of stack frame */ - uint32_t stacktop; /* Top of stack. Where values are pushed and popped from. */ - uint32_t capacity; + int32_t frame; /* Index of the stack frame */ + int32_t frametop; /* Index of top of stack frame */ + int32_t stacktop; /* Top of stack. Where values are pushed and popped from. */ + int32_t capacity; enum { DST_FIBER_PENDING = 0, DST_FIBER_ALIVE, @@ -191,7 +367,7 @@ struct DstFiber { struct DstStackFrame { DstFunction *func; uint32_t *pc; - uint32_t prevframe; + int32_t prevframe; }; /* Number of DstValues a frame takes up in the stack */ @@ -200,23 +376,23 @@ struct DstStackFrame { /* A dynamic array type. */ struct DstArray { DstValue *data; - uint32_t count; - uint32_t capacity; + int32_t count; + int32_t capacity; }; /* A bytebuffer type. Used as a mutable string or string builder. */ struct DstBuffer { uint8_t *data; - uint32_t count; - uint32_t capacity; + int32_t count; + int32_t capacity; }; /* A mutable associative data type. Backed by a hashtable. */ struct DstTable { DstValue *data; - uint32_t count; - uint32_t capacity; - uint32_t deleted; + int32_t count; + int32_t capacity; + int32_t deleted; }; /* Some function defintion flags */ @@ -225,16 +401,16 @@ struct DstTable { /* A function definition. Contains information needed to instantiate closures. */ 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. */ uint32_t *bytecode; uint32_t flags; - uint32_t slotcount; /* The amount of stack space required for the function */ - uint32_t arity; /* Not including varargs */ - uint32_t constants_length; - uint32_t bytecode_length; - uint32_t environments_length; + int32_t slotcount; /* The amount of stack space required for the function */ + int32_t arity; /* Not including varargs */ + int32_t constants_length; + int32_t bytecode_length; + int32_t environments_length; }; /* A fuction environment */ @@ -243,8 +419,8 @@ struct DstFuncEnv { DstFiber *fiber; DstValue *values; } as; - uint32_t length; /* Size of environment */ - uint32_t offset; /* Stack offset when values still on stack. If offset is 0, then + int32_t length; /* Size of environment */ + int32_t offset; /* Stack offset when values still on stack. If offset is 0, then environment is no longer on the stack. */ }; @@ -258,15 +434,15 @@ struct DstFunction { /* Defines a type for userdata */ struct DstUserType { const char *name; - int (*serialize)(void *data, uint32_t len); + int (*serialize)(void *data, size_t len); int (*deserialize)(); - void (*finalize)(void *data, uint32_t len); + void (*finalize)(void *data, size_t len); }; /* Contains information about userdata */ struct DstUserdataHeader { const DstUserType *type; - uint32_t size; + size_t size; }; /* 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; /* Array functions */ -DstArray *dst_array(uint32_t capacity); -DstArray *dst_array_init(DstArray *array, uint32_t capacity); +DstArray *dst_array(int32_t capacity); +DstArray *dst_array_init(DstArray *array, int32_t capacity); void dst_array_deinit(DstArray *array); -void dst_array_ensure(DstArray *array, uint32_t capacity); -void dst_array_setcount(DstArray *array, uint32_t count); +void dst_array_ensure(DstArray *array, int32_t capacity); +void dst_array_setcount(DstArray *array, int32_t count); void dst_array_push(DstArray *array, DstValue x); DstValue dst_array_pop(DstArray *array); DstValue dst_array_peek(DstArray *array); /* Buffer functions */ -DstBuffer *dst_buffer(uint32_t capacity); -DstBuffer *dst_buffer_init(DstBuffer *buffer, uint32_t capacity); +DstBuffer *dst_buffer(int32_t capacity); +DstBuffer *dst_buffer_init(DstBuffer *buffer, int32_t capacity); void dst_buffer_deinit(DstBuffer *buffer); -void dst_buffer_ensure(DstBuffer *buffer, uint32_t capacity); -void dst_buffer_extra(DstBuffer *buffer, uint32_t n); -void dst_buffer_push_bytes(DstBuffer *buffer, const uint8_t *string, uint32_t len); +void dst_buffer_ensure(DstBuffer *buffer, int32_t capacity); +void dst_buffer_extra(DstBuffer *buffer, int32_t n); +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_u8(DstBuffer *buffer, uint8_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); /* 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_hash(t) (dst_tuple_raw(t)[1]) -DstValue *dst_tuple_begin(uint32_t length); +#define dst_tuple_hash(t) ((dst_tuple_raw(t)[1])) +DstValue *dst_tuple_begin(int32_t length); 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_compare(const DstValue *lhs, const DstValue *rhs); /* 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_hash(s) (dst_string_raw(s)[1]) -uint8_t *dst_string_begin(uint32_t length); +#define dst_string_hash(s) ((dst_string_raw(s)[1])) +uint8_t *dst_string_begin(int32_t length); 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); 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_equalconst(const uint8_t *lhs, const uint8_t *rhs, uint32_t rlen, uint32_t rhash); -const uint8_t *dst_string_unique(const uint8_t *buf, uint32_t len); +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, int32_t len); const uint8_t *dst_cstring_unique(const char *s); const uint8_t *dst_description(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); /* 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_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_csymbolv(cstr) dst_wrap_symbol(dst_csymbol(cstr)) /* 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_capacity(t) (dst_struct_length(t) * 4) -#define dst_struct_hash(t) (dst_struct_raw(t)[1]) -DstValue *dst_struct_begin(uint32_t count); +#define dst_struct_hash(t) ((dst_struct_raw(t)[1])) +DstValue *dst_struct_begin(int32_t count); void dst_struct_put(DstValue *st, DstValue key, DstValue value); const DstValue *dst_struct_end(DstValue *st); 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); /* Table functions */ -DstTable *dst_table(uint32_t capacity); -DstTable *dst_table_init(DstTable *table, uint32_t capacity); +DstTable *dst_table(int32_t capacity); +DstTable *dst_table_init(DstTable *table, int32_t capacity); void dst_table_deinit(DstTable *table); DstValue dst_table_get(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); /* 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_fiber_frame(f) dst_stack_frame((f)->data + (f)->frame) 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_push2(DstFiber *fiber, DstValue x, DstValue y); 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); void dst_fiber_funcframe(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); /* Treat similar types through uniform interfaces for iteration */ -int dst_seq_view(DstValue seq, const DstValue **data, uint32_t *len); -int dst_chararray_view(DstValue str, const uint8_t **data, uint32_t *len); -int dst_hashtable_view(DstValue tab, const DstValue **data, uint32_t *len, uint32_t *cap); +int dst_seq_view(DstValue seq, const DstValue **data, int32_t *len); +int dst_chararray_view(DstValue str, const uint8_t **data, int32_t *len); +int dst_hashtable_view(DstValue tab, const DstValue **data, int32_t *len, int32_t *cap); /* Userdata */ #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) /* Value functions */ -int dst_truthy(DstValue v); 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); -uint32_t dst_calchash_array(const DstValue *array, uint32_t len); DstValue dst_get(DstValue ds, DstValue key); void dst_put(DstValue ds, DstValue key, DstValue value); DstValue dst_next(DstValue ds, DstValue key); -uint32_t dst_length(DstValue x); -uint32_t dst_capacity(DstValue x); -DstValue dst_getindex(DstValue ds, uint32_t index); -void dst_setindex(DstValue ds, DstValue value, uint32_t index); +int32_t dst_length(DstValue x); +int32_t dst_capacity(DstValue x); +DstValue dst_getindex(DstValue ds, int32_t index); +void dst_setindex(DstValue ds, DstValue value, int32_t index); /* Utils */ extern const char dst_base64[65]; -int64_t dst_real_to_integer(double real); -double dst_integer_to_real(int64_t integer); -uint32_t dst_array_calchash(const DstValue *array, uint32_t len); -uint32_t dst_string_calchash(const uint8_t *str, uint32_t len); +int32_t dst_array_calchash(const DstValue *array, int32_t len); +int32_t dst_string_calchash(const uint8_t *str, int32_t len); /* Parsing */ typedef enum { @@ -463,10 +635,10 @@ struct DstParseResult { const uint8_t *error; } result; DstValue map; - uint32_t bytes_read; + int32_t bytes_read; 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); /* VM functions */ @@ -477,21 +649,7 @@ int dst_run(DstValue callee); DstValue dst_transfer(DstFiber *fiber, DstValue x); /* 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 */ diff --git a/unittests/nanbox_test.c b/unittests/nanbox_test.c index 01f62123..315f3f46 100644 --- a/unittests/nanbox_test.c +++ b/unittests/nanbox_test.c @@ -35,25 +35,6 @@ union dst_t { * 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) */ -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..................| */ /* Non-double: t|11111111111|1ttt|xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx */ /* 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. */ #define DST_NANBOX_TYPEBITS 0x0007000000000000lu +#define DST_NANBOX_TAGBITS 0xFFFF000000000000lu #ifdef DST_64 #define DST_NANBOX_POINTERBITS 0x0000FFFFFFFFFFFFlu @@ -74,11 +56,16 @@ enum dst_t_tag { #define DST_NANBOX_QUIET_BIT 0x0008000000000000lu -#define dst_nanbox_isreal(x) (!isnan((x).real)) - #define dst_nanbox_tag(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) \ ((x).u64 & 0xFFFF000000000000lu) @@ -86,14 +73,14 @@ enum dst_t_tag { ((x).u64 & 0x0000FFFFFFFFFFFFlu) #define dst_nanbox_type(x) \ - (dst_nanbox_isreal(x) \ - ? DST_T_REAL \ - : (((x).u64 & DST_NANBOX_TYPEBITS) >> 48) | (((x).u64 >> 60) & 0x8)) + (isnan((x).real) \ + ? (((x).u64 & DST_NANBOX_TYPEBITS) >> 48) | (((x).u64 >> 60) & 0x8) \ + : DST_REAL) #define dst_nanbox_checktype(x, t) \ - (((t) == DST_T_REAL) \ + (((t) == DST_REAL) \ ? 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) { /* 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) { dst_t ret; ret.real = d; - /* Normalize NaNs to nil */ + /* Normalize NaNs */ if (d != d) - ret.u64 = dst_nanbox_tag(DST_T_NIL) << 48; + ret.u64 = dst_nanbox_tag(DST_REAL) << 48; 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) /* Wrap the simple types */ -#define dst_nanbox_wrap_nil() dst_nanbox_from_payload(DST_T_NIL, 0xFFFFFFFFFFFFlu) -#define dst_nanbox_wrap_true() dst_nanbox_from_payload(DST_T_TRUE, 0xFFFFFFFFFFFFlu) -#define dst_nanbox_wrap_false() dst_nanbox_from_payload(DST_T_FALSE, 0xFFFFFFFFFFFFlu) -#define dst_nanbox_wrap_boolean(b) dst_nanbox_from_payload((b) ? DST_T_TRUE : DST_T_FALSE, 0xFFFFFFFFFFFFlu) -#define dst_nanbox_wrap_integer(i) dst_nanbox_from_payload(DST_T_INTEGER, (uint32_t)(i)) +#define dst_nanbox_wrap_nil() dst_nanbox_from_payload(DST_NIL, 1) +#define dst_nanbox_wrap_true() dst_nanbox_from_payload(DST_TRUE, 1) +#define dst_nanbox_wrap_false() dst_nanbox_from_payload(DST_FALSE, 1) +#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_INTEGER, (uint32_t)(i)) #define dst_nanbox_wrap_real(r) dst_nanbox_from_double(r) #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) \ ((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) /* Wrap the pointer types */ -#define dst_nanbox_wrap_struct(s) dst_nanbox_wrap_((s), DST_T_STRUCT) -#define dst_nanbox_wrap_tuple(s) dst_nanbox_wrap_((s), DST_T_TUPLE) -#define dst_nanbox_wrap_fiber(s) dst_nanbox_wrap_((s), DST_T_FIBER) -#define dst_nanbox_wrap_array(s) dst_nanbox_wrap_((s), DST_T_ARRAY) -#define dst_nanbox_wrap_table(s) dst_nanbox_wrap_((s), DST_T_TABLE) -#define dst_nanbox_wrap_buffer(s) dst_nanbox_wrap_((s), DST_T_BUFFER) -#define dst_nanbox_wrap_string(s) dst_nanbox_wrap_((s), DST_T_STRING) -#define dst_nanbox_wrap_symbol(s) dst_nanbox_wrap_((s), DST_T_SYMBOL) -#define dst_nanbox_wrap_userdata(s) dst_nanbox_wrap_((s), DST_T_USERDATA) -#define dst_nanbox_wrap_function(s) dst_nanbox_wrap_((s), DST_T_FUNCTION) -#define dst_nanbox_wrap_cfunction(s) dst_nanbox_wrap_((s), DST_T_CFUNCTION) +#define dst_nanbox_wrap_struct(s) dst_nanbox_wrap_((s), DST_STRUCT) +#define dst_nanbox_wrap_tuple(s) dst_nanbox_wrap_((s), DST_TUPLE) +#define dst_nanbox_wrap_fiber(s) dst_nanbox_wrap_((s), DST_FIBER) +#define dst_nanbox_wrap_array(s) dst_nanbox_wrap_((s), DST_ARRAY) +#define dst_nanbox_wrap_table(s) dst_nanbox_wrap_((s), DST_TABLE) +#define dst_nanbox_wrap_buffer(s) dst_nanbox_wrap_((s), DST_BUFFER) +#define dst_nanbox_wrap_string(s) dst_nanbox_wrap_((s), DST_STRING) +#define dst_nanbox_wrap_symbol(s) dst_nanbox_wrap_((s), DST_SYMBOL) +#define dst_nanbox_wrap_userdata(s) dst_nanbox_wrap_((s), DST_USERDATA) +#define dst_nanbox_wrap_function(s) dst_nanbox_wrap_((s), DST_FUNCTION) +#define dst_nanbox_wrap_cfunction(s) dst_nanbox_wrap_((s), DST_CFUNCTION) /* Unwrap the pointer types */ #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)) void dst_nanbox_print(dst_t x) { - assert(dst_nanbox_checktype(x, dst_nanbox_type(x))); printf("hex: 0x%lx, " "description: ", x.u64); switch (dst_nanbox_type(x)) { - case DST_T_NIL: + case DST_NIL: printf("nil\n"); break; - case DST_T_TRUE: + case DST_TRUE: printf("true\n"); break; - case DST_T_FALSE: + case DST_FALSE: printf("false\n"); break; - case DST_T_INTEGER: + case DST_INTEGER: printf("%dI\n", dst_nanbox_unwrap_integer(x)); break; - case DST_T_STRUCT: + case DST_STRUCT: printf("\n", dst_nanbox_unwrap_struct(x)); break; - case DST_T_TUPLE: + case DST_TUPLE: printf("\n", dst_nanbox_unwrap_tuple(x)); break; - case DST_T_FIBER: + case DST_FIBER: printf("\n", dst_nanbox_unwrap_fiber(x)); break; - case DST_T_ARRAY: + case DST_ARRAY: printf("\n", dst_nanbox_unwrap_array(x)); break; - case DST_T_TABLE: + case DST_TABLE: printf("\n", dst_nanbox_unwrap_table(x)); break; - case DST_T_STRING: + case DST_STRING: printf("\n", dst_nanbox_unwrap_string(x)); break; - case DST_T_SYMBOL: + case DST_SYMBOL: printf("\n", dst_nanbox_unwrap_symbol(x)); break; - case DST_T_USERDATA: + case DST_USERDATA: printf("\n", dst_nanbox_unwrap_userdata(x)); break; - case DST_T_FUNCTION: + case DST_FUNCTION: printf("\n", dst_nanbox_unwrap_function(x)); break; - case DST_T_CFUNCTION: + case DST_CFUNCTION: printf("\n", dst_nanbox_unwrap_cfunction(x)); break; - case DST_T_BUFFER: + case DST_BUFFER: printf("\n", dst_nanbox_unwrap_buffer(x)); break; default: 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)); break; } + assert(dst_nanbox_checktype(x, dst_nanbox_type(x))); } int main() { @@ -242,6 +229,10 @@ int main() { 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(19236910.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_true()); 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(0));