mirror of
https://github.com/janet-lang/janet
synced 2025-11-12 05:23:02 +00:00
WIP integrating nanbox support back into code.
This commit is contained in:
18
core/array.c
18
core/array.c
@@ -23,7 +23,8 @@
|
||||
#include <dst/dst.h>
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
133
core/asm.c
133
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;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <dst/dst.h>
|
||||
|
||||
/* 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;
|
||||
|
||||
58
core/fiber.c
58
core/fiber.c
@@ -23,7 +23,7 @@
|
||||
#include <dst/dst.h>
|
||||
|
||||
/* 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);
|
||||
|
||||
80
core/gc.c
80
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);
|
||||
|
||||
16
core/parse.c
16
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);
|
||||
}
|
||||
|
||||
151
core/string.c
151
core/string.c
@@ -23,9 +23,9 @@
|
||||
#include <dst/dst.h>
|
||||
|
||||
/* 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, "<cycle ");
|
||||
integer_to_string_b(&p->buffer, check.as.integer);
|
||||
integer_to_string_b(&p->buffer, dst_unwrap_integer(check));
|
||||
dst_buffer_push_cstring(&p->buffer, ">");
|
||||
} 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);
|
||||
}
|
||||
|
||||
@@ -23,17 +23,17 @@
|
||||
#include <dst/dst.h>
|
||||
|
||||
/* 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)
|
||||
|
||||
@@ -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] = '-';
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
#include <dst/dst.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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");
|
||||
|
||||
54
core/table.c
54
core/table.c
@@ -23,7 +23,7 @@
|
||||
#include <dst/dst.h>
|
||||
|
||||
/* 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);
|
||||
|
||||
26
core/tuple.c
26
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;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <dst/dst.h>
|
||||
|
||||
/* 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);
|
||||
|
||||
70
core/util.c
70
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;
|
||||
}
|
||||
|
||||
239
core/value.c
239
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;
|
||||
}
|
||||
}
|
||||
|
||||
168
core/vm.c
168
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;
|
||||
}
|
||||
|
||||
|
||||
86
core/wrap.c
86
core/wrap.c
@@ -22,6 +22,49 @@
|
||||
|
||||
#include <dst/dst.h>
|
||||
|
||||
#ifdef DST_NANBOX
|
||||
|
||||
void *dst_nanbox_to_pointer(dst_t x) {
|
||||
/* We need to do this shift to keep the higher bits of the pointer
|
||||
* the same as bit 47 as required by the x86 architecture. We may save
|
||||
* an instruction if we do x.u64 & DST_NANBOX_POINTERBITS, but this 0s
|
||||
* the high bits, and may make the pointer non-canocial on x86. */
|
||||
x.i64 = (x.i64 << 16) >> 16;
|
||||
return x.pointer;
|
||||
}
|
||||
|
||||
DstValue dst_nanbox_from_pointer(void *p, uint64_t tagmask) {
|
||||
DstValue ret;
|
||||
ret.pointer = p;
|
||||
ret.u64 &= DST_NANBOX_POINTERBITS;
|
||||
ret.u64 |= tagmask;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DstValue dst_nanbox_from_double(double d) {
|
||||
DstValue ret;
|
||||
ret.real = d;
|
||||
/* Normalize NaNs */
|
||||
if (d != d)
|
||||
ret.u64 = dst_nanbox_tag(DST_REAL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DstValue dst_nanbox_from_bits(uint64_t bits) {
|
||||
dst_t ret;
|
||||
ret.u64 = bits;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dst_nanbox_memempty(DstValue *mem, uint32_t count) {
|
||||
uint32_t i;
|
||||
for (i = 0; i < count; i++) {
|
||||
mem[i] = dst_wrap_nil();
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Wrapper functions wrap a data type that is used from C into a
|
||||
* 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
|
||||
|
||||
Reference in New Issue
Block a user