mirror of
https://github.com/janet-lang/janet
synced 2024-12-25 07:50:27 +00:00
Convert get, put and length to normal functions, not c functions.
This commit is contained in:
parent
0cf10946b0
commit
363a17ff8c
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
160
src/core/value.c
160
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;
|
||||
}
|
||||
}
|
||||
|
252
src/core/vm.c
252
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();
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user