mirror of
https://github.com/janet-lang/janet
synced 2025-12-03 15:18:10 +00:00
Convert get, put and length to normal functions, not c functions.
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user