diff --git a/src/assembler/asm.c b/src/assembler/asm.c index 2d33f37e..a301b337 100644 --- a/src/assembler/asm.c +++ b/src/assembler/asm.c @@ -475,6 +475,18 @@ static uint32_t read_instruction( return instr; } +/* Helper to get from a structure */ +static Dst dst_get(Dst ds, Dst key) { + switch (dst_type(ds)) { + default: + return dst_wrap_nil(); + case DST_TABLE: + return dst_table_get(dst_unwrap_table(ds), key); + case DST_STRUCT: + return dst_struct_get(dst_unwrap_struct(ds), key); + } +} + /* Helper to assembly. Return the assembly result */ static DstAssembleResult dst_asm1(DstAssembler *parent, Dst source, int flags) { DstAssembleResult result; diff --git a/src/compiler/compile.c b/src/compiler/compile.c index a24c43d9..1ed68c32 100644 --- a/src/compiler/compile.c +++ b/src/compiler/compile.c @@ -66,6 +66,19 @@ int dstc_iserr(DstFopts *opts) { return (opts->compiler->result.status == DST_COMPILE_ERROR); } +/* Get the next key in an associative data structure. Used for iterating through an + * associative data structure. */ +const DstKV *dstc_next(Dst ds, const DstKV *kv) { + switch(dst_type(ds)) { + default: + return NULL; + case DST_TABLE: + return (const DstKV *) dst_table_next(dst_unwrap_table(ds), kv); + case DST_STRUCT: + return dst_struct_next(dst_unwrap_struct(ds), kv); + } +} + /* Allocate a slot index */ int32_t dstc_lsloti(DstCompiler *c) { DstScope *scope = &dst_v_last(c->scopes); @@ -257,22 +270,24 @@ DstSlot dstc_resolve( /* Symbol not found - check for global */ { - Dst check = dst_table_get(c->env, dst_wrap_symbol(sym)); - Dst ref; - if (!(dst_checktype(check, DST_STRUCT) || dst_checktype(check, DST_TABLE))) { - dstc_error(c, ast, dst_formatc("unknown symbol %q", sym)); - return dstc_cslot(dst_wrap_nil()); - } - ref = dst_get(check, dst_csymbolv(":ref")); - if (dst_checktype(ref, DST_ARRAY)) { - DstSlot ret = dstc_cslot(ref); - /* TODO save type info */ - ret.flags |= DST_SLOT_REF | DST_SLOT_NAMED | DST_SLOT_MUTABLE | DST_SLOTTYPE_ANY; - ret.flags &= ~DST_SLOT_CONSTANT; - return ret; - } else { - Dst value = dst_get(check, dst_csymbolv(":value")); - return dstc_cslot(value); + Dst check; + DstBindingType btype = dst_env_resolve(c->env, sym, &check); + switch (btype) { + default: + case DST_BINDING_NONE: + dstc_error(c, ast, dst_formatc("unknown symbol %q", sym)); + return dstc_cslot(dst_wrap_nil()); + case DST_BINDING_DEF: + case DST_BINDING_MACRO: /* Macro should function like defs when not in calling pos */ + return dstc_cslot(check); + case DST_BINDING_VAR: + { + DstSlot ret = dstc_cslot(check); + /* TODO save type info */ + ret.flags |= DST_SLOT_REF | DST_SLOT_NAMED | DST_SLOT_MUTABLE | DST_SLOTTYPE_ANY; + ret.flags &= ~DST_SLOT_CONSTANT; + return ret; + } } } @@ -627,7 +642,7 @@ DstSM *dstc_toslotskv(DstCompiler *c, Dst ds) { DstSM *ret = NULL; const DstKV *kv = NULL; DstFopts subopts = dstc_fopts_default(c); - while ((kv = dst_next(ds, kv))) { + while ((kv = dstc_next(ds, kv))) { DstSM km, vm; km.slot = dstc_value(subopts, kv->key); km.map = dst_ast_node(kv->key); @@ -807,25 +822,22 @@ recur: /* Symbols could be specials */ headval = dst_ast_unwrap1(tup[0]); if (dst_checktype(headval, DST_SYMBOL)) { - const DstSpecial *s = dstc_special(dst_unwrap_symbol(headval)); + const uint8_t *headsym = dst_unwrap_symbol(headval); + const DstSpecial *s = dstc_special(headsym); if (NULL != s) { ret = s->compile(opts, ast, dst_tuple_length(tup) - 1, tup + 1); compiled = 1; } else { /* Check macro */ - DstTable *env = c->env; - Dst fn; - Dst entry = dst_table_get(env, headval); - for (;;) { - if (dst_checktype(entry, DST_NIL)) break; - if (dst_checktype(dst_get(entry, dst_csymbolv(":macro")), DST_NIL)) break; - fn = dst_get(entry, dst_csymbolv(":value")); - if (!dst_checktype(fn, DST_FUNCTION)) break; + Dst macVal; + DstBindingType btype = dst_env_resolve(c->env, headsym, &macVal); + if (btype == DST_BINDING_MACRO && + dst_checktype(macVal, DST_FUNCTION)) { if (macrorecur++ > DST_RECURSION_GUARD) { dstc_cerror(c, ast, "macro expansion recursed too deeply"); return dstc_cslot(dst_wrap_nil()); } else { - DstFunction *f = dst_unwrap_function(fn); + DstFunction *f = dst_unwrap_function(macVal); int lock = dst_gclock(); DstSignal status = dst_call(f, dst_tuple_length(tup) - 1, tup + 1, &x); dst_gcunlock(lock); @@ -843,6 +855,7 @@ recur: /* Compile the head of the tuple */ subopts.flags = DST_FUNCTION | DST_CFUNCTION; head = dstc_value(subopts, tup[0]); + /* Add compile function call */ ret = dstc_call(opts, ast, dstc_toslots(c, tup + 1, dst_tuple_length(tup) - 1), head); } } diff --git a/src/compiler/compile.h b/src/compiler/compile.h index b912a757..fb5674c9 100644 --- a/src/compiler/compile.h +++ b/src/compiler/compile.h @@ -154,6 +154,9 @@ const DstSpecial *dstc_special(const uint8_t *name); /* Check error */ int dstc_iserr(DstFopts *opts); +/* Helper for iterating tables and structs */ +const DstKV *dstc_next(Dst ds, const DstKV *kv); + /* Allocate a slot index */ int32_t dstc_lsloti(DstCompiler *c); diff --git a/src/compiler/specials.c b/src/compiler/specials.c index 40f413b0..321b8636 100644 --- a/src/compiler/specials.c +++ b/src/compiler/specials.c @@ -65,10 +65,11 @@ static void destructure(DstCompiler *c, Dst left, DstSlot right, case DST_ARRAY: { int32_t i, len, localright, localsub; - len = dst_length(left); + const Dst *values; + dst_seq_view(left, &values, &len); for (i = 0; i < len; i++) { DstSlot newright; - Dst subval = dst_getindex(left, i); + Dst subval = values[i]; localright = dstc_preread(c, ast, 0xFF, 1, right); localsub = dstc_lslotn(c, 0xFF, 3); if (i < 0x100) { @@ -104,7 +105,7 @@ static void destructure(DstCompiler *c, Dst left, DstSlot right, { int32_t localright, localsub; const DstKV *kv = NULL; - while ((kv = dst_next(left, kv))) { + while ((kv = dstc_next(left, kv))) { DstSlot newright; DstSlot kslot = dstc_cslot(dst_ast_unwrap(kv->key)); Dst subval = kv->value; diff --git a/src/compiler/stl.c b/src/compiler/stl.c index f940af7e..0f2d5f6f 100644 --- a/src/compiler/stl.c +++ b/src/compiler/stl.c @@ -46,9 +46,6 @@ static const DstReg cfuns[] = { {"struct", dst_core_struct}, {"buffer", dst_core_buffer}, {"gensym", dst_core_gensym}, - {"get", dst_core_get}, - {"put", dst_core_put}, - {"length", dst_core_length}, {"gccollect", dst_core_gccollect}, {"gcsetinterval", dst_core_gcsetinterval}, {"gcinterval", dst_core_gcinterval}, @@ -100,6 +97,18 @@ DstTable *dst_stl_env(int flags) { DOP_RESUME | (1 << 24), DOP_RETURN }; + static uint32_t get_asm[] = { + DOP_GET | (1 << 24), + DOP_RETURN + }; + static uint32_t put_asm[] = { + DOP_PUT | (1 << 16) | (2 << 24), + DOP_RETURN + }; + static uint32_t length_asm[] = { + DOP_LENGTH, + DOP_RETURN + }; DstTable *env = dst_table(0); Dst ret = dst_wrap_table(env); @@ -112,6 +121,9 @@ DstTable *dst_stl_env(int flags) { dst_env_def(env, "apply1", dst_wrap_function(dst_quick_asm("apply1", 2, 0, 2, apply_asm, sizeof(apply_asm)))); dst_env_def(env, "yield", dst_wrap_function(dst_quick_asm("yield", 1, 0, 2, yield_asm, sizeof(yield_asm)))); dst_env_def(env, "resume", dst_wrap_function(dst_quick_asm("resume", 2, 0, 2, resume_asm, sizeof(resume_asm)))); + dst_env_def(env, "get", dst_wrap_function(dst_quick_asm("get", 2, 0, 2, get_asm, sizeof(get_asm)))); + dst_env_def(env, "put", dst_wrap_function(dst_quick_asm("put", 3, 0, 3, put_asm, sizeof(put_asm)))); + dst_env_def(env, "length", dst_wrap_function(dst_quick_asm("length", 1, 0, 1, length_asm, sizeof(length_asm)))); dst_env_def(env, "VERSION", dst_cstringv(DST_VERSION)); diff --git a/src/core/corelib.c b/src/core/corelib.c index 4e2dc9ef..96a8ea8e 100644 --- a/src/core/corelib.c +++ b/src/core/corelib.c @@ -180,37 +180,6 @@ int dst_core_gensym(DstArgs args) { } } -int dst_core_length(DstArgs args) { - DST_FIXARITY(args, 1); - DST_RETURN_INTEGER(args, dst_length(args.v[0])); -} - -int dst_core_get(DstArgs args) { - int32_t i; - Dst ds; - DST_MINARITY(args, 1); - ds = args.v[0]; - for (i = 1; i < args.n; i++) { - ds = dst_get(ds, args.v[i]); - if (dst_checktype(ds, DST_NIL)) - break; - } - DST_RETURN(args, ds); -} - -int dst_core_put(DstArgs args) { - Dst ds, key, value; - DstArgs subargs = args; - DST_MINARITY(args, 3); - subargs.n -= 2; - if (dst_core_get(subargs)) return 1; - ds = *args.ret; - key = args.v[args.n - 2]; - value = args.v[args.n - 1]; - dst_put(ds, key, value); - return 0; -} - int dst_core_gccollect(DstArgs args) { (void) args; dst_collect(); @@ -252,13 +221,14 @@ int dst_core_next(DstArgs args) { kv = dst_checktype(args.v[1], DST_NIL) ? NULL : dst_table_find(t, args.v[1]); + kv = dst_table_next(t, kv); } else { const DstKV *st = dst_unwrap_struct(ds); kv = dst_checktype(args.v[1], DST_NIL) ? NULL : dst_struct_find(st, args.v[1]); + kv = dst_struct_next(st, kv); } - kv = dst_next(ds, kv); if (kv) { DST_RETURN(args, kv->key); } diff --git a/src/core/util.c b/src/core/util.c index 6b4152be..18ec7427 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -138,17 +138,27 @@ void dst_env_cfuns(DstTable *env, const DstReg *cfuns) { } } -/* Resolve a symbol in the environment. Undefined symbols will - * resolve to nil */ -Dst dst_env_resolve(DstTable *env, const char *name) { +/* Resolve a symbol in the environment */ +DstBindingType dst_env_resolve(DstTable *env, const uint8_t *sym, Dst *out) { Dst ref; - Dst entry = dst_table_get(env, dst_csymbolv(name)); - if (dst_checktype(entry, DST_NIL)) return dst_wrap_nil(); - ref = dst_get(entry, dst_csymbolv(":ref")); - if (dst_checktype(ref, DST_ARRAY)) { - return dst_getindex(ref, 0); + DstTable *entry_table; + Dst entry = dst_table_get(env, dst_wrap_symbol(sym)); + if (!dst_checktype(entry, DST_TABLE)) + return DST_BINDING_NONE; + entry_table = dst_unwrap_table(entry); + if (!dst_checktype( + dst_table_get(entry_table, dst_csymbolv(":macro")), + DST_NIL)) { + *out = dst_table_get(entry_table, dst_csymbolv(":value")); + return DST_BINDING_MACRO; } - return dst_get(entry, dst_csymbolv(":value")); + ref = dst_table_get(entry_table, dst_csymbolv(":ref")); + if (dst_checktype(ref, DST_ARRAY)) { + *out = ref; + return DST_BINDING_VAR; + } + *out = dst_table_get(entry_table, dst_csymbolv(":value")); + return DST_BINDING_DEF; } /* Get module from the arguments passed to library */ diff --git a/src/core/value.c b/src/core/value.c index da853190..b3a8437d 100644 --- a/src/core/value.c +++ b/src/core/value.c @@ -154,163 +154,3 @@ int dst_compare(Dst x, Dst y) { } return (dst_type(x) < dst_type(y)) ? -1 : 1; } - -/* Get a value out af an associated data structure. For invalid - * data structure or invalid key, returns nil. */ -Dst dst_get(Dst ds, Dst key) { - switch (dst_type(ds)) { - case DST_ARRAY: - 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 (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 (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 (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(dst_unwrap_struct(ds), key); - case DST_TABLE: - return dst_table_get(dst_unwrap_table(ds), key); - default: - break; - } - return dst_wrap_nil(); -} - -/* Set a value in an associative data structure. Returns possible - * error message, and NULL if no error. */ -void dst_put(Dst ds, Dst key, Dst value) { - switch (dst_type(ds)) { - case DST_ARRAY: - { - int32_t index; - DstArray *array = dst_unwrap_array(ds); - if (!dst_checktype(key, DST_INTEGER) || dst_unwrap_integer(key) < 0) - return; - index = dst_unwrap_integer(key); - if (index == INT32_MAX) return; - if (index >= array->count) { - dst_array_setcount(array, index + 1); - } - array->data[index]= value; - return; - } - case DST_BUFFER: - { - int32_t index; - DstBuffer *buffer = dst_unwrap_buffer(ds); - if (!dst_checktype(key, DST_INTEGER) || dst_unwrap_integer(key) < 0) - return; - index = dst_unwrap_integer(key); - if (index == INT32_MAX) return; - if (!dst_checktype(value, DST_INTEGER)) - return; - if (index >= buffer->count) { - dst_buffer_setcount(buffer, index + 1); - } - buffer->data[index] = (uint8_t) (dst_unwrap_integer(value) & 0xFF); - return; - } - case DST_TABLE: - dst_table_put(dst_unwrap_table(ds), key, value); - return; - default: - return; - } -} - -/* Get the next key in an associative data structure. Used for iterating through an - * associative data structure. */ -const DstKV *dst_next(Dst ds, const DstKV *kv) { - switch(dst_type(ds)) { - default: - return NULL; - case DST_TABLE: - return (const DstKV *) dst_table_next(dst_unwrap_table(ds), kv); - case DST_STRUCT: - return dst_struct_next(dst_unwrap_struct(ds), kv); - } -} - -/* Get the length of an object. Returns errors for invalid types */ -int32_t dst_length(Dst x) { - switch (dst_type(x)) { - default: - return 0; - case DST_STRING: - case DST_SYMBOL: - return dst_string_length(dst_unwrap_string(x)); - case DST_ARRAY: - return dst_unwrap_array(x)->count; - case DST_BUFFER: - return dst_unwrap_buffer(x)->count; - case DST_TUPLE: - return dst_tuple_length(dst_unwrap_tuple(x)); - case DST_STRUCT: - return dst_struct_length(dst_unwrap_struct(x)); - case DST_TABLE: - return dst_unwrap_table(x)->count; - } -} - -/* Index into a data structure. Returns nil for out of bounds or invlalid data structure */ -Dst dst_getindex(Dst ds, int32_t index) { - switch (dst_type(ds)) { - default: - return dst_wrap_nil(); - case DST_STRING: - case DST_SYMBOL: - 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 >= dst_unwrap_array(ds)->count) return dst_wrap_nil(); - return dst_unwrap_array(ds)->data[index]; - case DST_BUFFER: - 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(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(Dst ds, Dst value, int32_t index) { - switch (dst_type(ds)) { - default: - return; - case DST_ARRAY: - if (index >= dst_unwrap_array(ds)->count) { - dst_array_ensure(dst_unwrap_array(ds), 2 * index); - dst_unwrap_array(ds)->count = index + 1; - } - dst_unwrap_array(ds)->data[index] = value; - return; - case DST_BUFFER: - 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; - } - dst_unwrap_buffer(ds)->data[index] = dst_unwrap_integer(value); - return; - } -} diff --git a/src/core/vm.c b/src/core/vm.c index fbb97857..dcb5e18a 100644 --- a/src/core/vm.c +++ b/src/core/vm.c @@ -769,37 +769,241 @@ static void *op_lookup[255] = { } VM_OP(DOP_PUT) - dst_put(stack[oparg(1, 0xFF)], - stack[oparg(2, 0xFF)], - stack[oparg(3, 0xFF)]); - ++pc; - vm_checkgc_next(); + { + Dst ds = stack[oparg(1, 0xFF)]; + Dst key = stack[oparg(2, 0xFF)]; + Dst value = stack[oparg(3, 0xFF)]; + switch (dst_type(ds)) { + default: + vm_throw("expected mutable data structure"); + case DST_ARRAY: + { + int32_t index; + DstArray *array = dst_unwrap_array(ds); + if (!dst_checktype(key, DST_INTEGER) || dst_unwrap_integer(key) < 0) + vm_throw("expected non-negative integer key"); + index = dst_unwrap_integer(key); + if (index == INT32_MAX) + vm_throw("key too large"); + if (index >= array->count) { + dst_array_setcount(array, index + 1); + } + array->data[index] = value; + break; + } + case DST_BUFFER: + { + int32_t index; + DstBuffer *buffer = dst_unwrap_buffer(ds); + if (!dst_checktype(key, DST_INTEGER) || dst_unwrap_integer(key) < 0) + vm_throw("expected non-negative integer key"); + index = dst_unwrap_integer(key); + if (index == INT32_MAX) + vm_throw("key too large"); + if (!dst_checktype(value, DST_INTEGER)) + vm_throw("expected integer value"); + if (index >= buffer->count) { + dst_buffer_setcount(buffer, index + 1); + } + buffer->data[index] = (uint8_t) (dst_unwrap_integer(value) & 0xFF); + break; + } + case DST_TABLE: + dst_table_put(dst_unwrap_table(ds), key, value); + break; + } + ++pc; + vm_checkgc_next(); + } VM_OP(DOP_PUT_INDEX) - dst_setindex(stack[oparg(1, 0xFF)], - stack[oparg(2, 0xFF)], - oparg(3, 0xFF)); - ++pc; - vm_checkgc_next(); + { + Dst ds = stack[oparg(1, 0xFF)]; + Dst value = stack[oparg(2, 0xFF)]; + int32_t index = oparg(3, 0xFF); + switch (dst_type(ds)) { + default: + vm_throw("expected mutable indexed data structure"); + case DST_ARRAY: + if (index >= dst_unwrap_array(ds)->count) { + dst_array_ensure(dst_unwrap_array(ds), 2 * index); + dst_unwrap_array(ds)->count = index + 1; + } + dst_unwrap_array(ds)->data[index] = value; + break; + case DST_BUFFER: + if (!dst_checktype(value, DST_INTEGER))\ + vm_throw("expected integer to set in buffer"); + if (index >= dst_unwrap_buffer(ds)->count) { + dst_buffer_ensure(dst_unwrap_buffer(ds), 2 * index); + dst_unwrap_buffer(ds)->count = index + 1; + } + dst_unwrap_buffer(ds)->data[index] = dst_unwrap_integer(value); + break; + } + ++pc; + vm_checkgc_next(); + } VM_OP(DOP_GET) - stack[oparg(1, 0xFF)] = dst_get( - stack[oparg(2, 0xFF)], - stack[oparg(3, 0xFF)]); - ++pc; - vm_next(); + { + Dst ds = stack[oparg(2, 0xFF)]; + Dst key = stack[oparg(3, 0xFF)]; + Dst value; + switch (dst_type(ds)) { + default: + vm_throw("expected data structure"); + case DST_STRUCT: + value = dst_struct_get(dst_unwrap_struct(ds), key); + break; + case DST_TABLE: + value = dst_table_get(dst_unwrap_table(ds), key); + break; + case DST_ARRAY: + { + DstArray *array = dst_unwrap_array(ds); + int32_t index; + if (!dst_checktype(key, DST_INTEGER)) + vm_throw("expected integer key"); + index = dst_unwrap_integer(key); + if (index < 0 || index >= array->count) { + /*vm_throw("index out of bounds");*/ + value = dst_wrap_nil(); + } else { + value = array->data[index]; + } + break; + } + case DST_TUPLE: + { + const Dst *tuple = dst_unwrap_tuple(ds); + int32_t index; + if (!dst_checktype(key, DST_INTEGER)) + vm_throw("expected integer key"); + index = dst_unwrap_integer(key); + if (index < 0 || index >= dst_tuple_length(tuple)) { + /*vm_throw("index out of bounds");*/ + value = dst_wrap_nil(); + } else { + value = tuple[index]; + } + break; + } + case DST_BUFFER: + { + DstBuffer *buffer = dst_unwrap_buffer(ds); + int32_t index; + if (!dst_checktype(key, DST_INTEGER)) + vm_throw("expected integer key"); + index = dst_unwrap_integer(key); + if (index < 0 || index >= buffer->count) { + /*vm_throw("index out of bounds");*/ + value = dst_wrap_nil(); + } else { + value = dst_wrap_integer(buffer->data[index]); + } + break; + } + case DST_STRING: + case DST_SYMBOL: + { + const uint8_t *str = dst_unwrap_string(ds); + int32_t index; + if (!dst_checktype(key, DST_INTEGER)) + vm_throw("expected integer key"); + index = dst_unwrap_integer(key); + if (index < 0 || index >= dst_string_length(str)) { + /*vm_throw("index out of bounds");*/ + value = dst_wrap_nil(); + } else { + value = dst_wrap_integer(str[index]); + } + break; + } + } + stack[oparg(1, 0xFF)] = value; + ++pc; + vm_next(); + } VM_OP(DOP_GET_INDEX) - stack[oparg(1, 0xFF)] = dst_getindex( - stack[oparg(2, 0xFF)], - oparg(3, 0xFF)); - ++pc; - vm_next(); + { + Dst ds = stack[oparg(2, 0xFF)]; + int32_t index = oparg(3, 0xFF); + Dst value; + switch (dst_type(ds)) { + default: + vm_throw("expected indexed data structure"); + case DST_STRING: + case DST_SYMBOL: + if (index >= dst_string_length(dst_unwrap_string(ds))) { + /*vm_throw("index out of bounds");*/ + value = dst_wrap_nil(); + } else { + value = dst_wrap_integer(dst_unwrap_string(ds)[index]); + } + break; + case DST_ARRAY: + if (index >= dst_unwrap_array(ds)->count) { + /*vm_throw("index out of bounds");*/ + value = dst_wrap_nil(); + } else { + value = dst_unwrap_array(ds)->data[index]; + } + break; + case DST_BUFFER: + if (index >= dst_unwrap_buffer(ds)->count) { + /*vm_throw("index out of bounds");*/ + value = dst_wrap_nil(); + } else { + value = dst_wrap_integer(dst_unwrap_buffer(ds)->data[index]); + } + break; + case DST_TUPLE: + if (index >= dst_tuple_length(dst_unwrap_tuple(ds))) { + /*vm_throw("index out of bounds");*/ + value = dst_wrap_nil(); + } else { + value = dst_unwrap_tuple(ds)[index]; + } + break; + } + stack[oparg(1, 0xFF)] = value; + ++pc; + vm_next(); + } VM_OP(DOP_LENGTH) - stack[oparg(1, 0xFF)] = dst_wrap_integer(dst_length(stack[oparg(2, 0xFFFF)])); - ++pc; - vm_next(); + { + Dst x = stack[oparg(2, 0xFFFF)]; + int32_t len; + switch (dst_type(x)) { + default: + vm_throw("expected data structure"); + case DST_STRING: + case DST_SYMBOL: + len = dst_string_length(dst_unwrap_string(x)); + break; + case DST_ARRAY: + len = dst_unwrap_array(x)->count; + break; + case DST_BUFFER: + len = dst_unwrap_buffer(x)->count; + break; + case DST_TUPLE: + len = dst_tuple_length(dst_unwrap_tuple(x)); + break; + case DST_STRUCT: + len = dst_struct_length(dst_unwrap_struct(x)); + break; + case DST_TABLE: + len = dst_unwrap_table(x)->count; + break; + } + stack[oparg(1, 0xFF)] = dst_wrap_integer(len); + ++pc; + vm_next(); + } /* Return from c function. Simpler than returning from dst function */ vm_return_cfunc: @@ -808,7 +1012,7 @@ static void *op_lookup[255] = { if (fiber->frame == 0) goto vm_exit; stack = fiber->data + fiber->frame; stack[oparg(1, 0xFF)] = retreg; - pc++; + ++pc; vm_checkgc_next(); } diff --git a/src/include/dst/dst.h b/src/include/dst/dst.h index f413b870..9d2f557b 100644 --- a/src/include/dst/dst.h +++ b/src/include/dst/dst.h @@ -173,12 +173,6 @@ int dst_verify(DstFuncDef *def); int dst_equals(Dst x, Dst y); int32_t dst_hash(Dst x); int dst_compare(Dst x, Dst y); -Dst dst_get(Dst ds, Dst key); -void dst_put(Dst ds, Dst key, Dst value); -const DstKV *dst_next(Dst ds, const DstKV *kv); -int32_t dst_length(Dst x); -Dst dst_getindex(Dst ds, int32_t index); -void dst_setindex(Dst ds, Dst value, int32_t index); int dst_cstrcmp(const uint8_t *str, const char *other); /* VM functions */ @@ -189,10 +183,16 @@ DstSignal dst_continue(DstFiber *fiber, Dst in, Dst *out); DstSignal dst_call(DstFunction *fun, int32_t argn, const Dst *argv, Dst *out); /* Env helpers */ +typedef enum { + DST_BINDING_NONE, + DST_BINDING_DEF, + DST_BINDING_VAR, + DST_BINDING_MACRO +} DstBindingType; void dst_env_def(DstTable *env, const char *name, Dst val); void dst_env_var(DstTable *env, const char *name, Dst val); void dst_env_cfuns(DstTable *env, const DstReg *cfuns); -Dst dst_env_resolve(DstTable *env, const char *name); +DstBindingType dst_env_resolve(DstTable *env, const uint8_t *sym, Dst *out); DstTable *dst_env_arg(DstArgs args); /* STL */ diff --git a/src/include/dst/dstcorelib.h b/src/include/dst/dstcorelib.h index 99e3ebc3..d71dc271 100644 --- a/src/include/dst/dstcorelib.h +++ b/src/include/dst/dstcorelib.h @@ -80,9 +80,6 @@ int dst_core_table(DstArgs args); int dst_core_struct(DstArgs args); int dst_core_buffer(DstArgs args); int dst_core_gensym(DstArgs args); -int dst_core_length(DstArgs args); -int dst_core_get(DstArgs args); -int dst_core_put(DstArgs args); int dst_core_type(DstArgs args); int dst_core_next(DstArgs args); int dst_core_hash(DstArgs args);