mirror of
https://github.com/janet-lang/janet
synced 2025-01-13 00:50:26 +00:00
Better working panic implementation and more cleanup in main vm loop.
This commit is contained in:
parent
cd6a7793e8
commit
5b62c8e6db
@ -681,7 +681,7 @@ const uint8_t *janet_formatc(const char *format, ...) {
|
|||||||
number_to_string_b(bufp, va_arg(args, double));
|
number_to_string_b(bufp, va_arg(args, double));
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
integer_to_string_b(bufp, va_arg(args, int32_t));
|
integer_to_string_b(bufp, va_arg(args, long));
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
{
|
{
|
||||||
@ -708,7 +708,7 @@ const uint8_t *janet_formatc(const char *format, ...) {
|
|||||||
}
|
}
|
||||||
case 'T':
|
case 'T':
|
||||||
{
|
{
|
||||||
int types = va_arg(args, int32_t);
|
int types = va_arg(args, long);
|
||||||
pushtypes(bufp, types);
|
pushtypes(bufp, types);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -145,13 +145,14 @@ int janet_compare(Janet x, Janet y) {
|
|||||||
return (janet_type(x) < janet_type(y)) ? -1 : 1;
|
return (janet_type(x) < janet_type(y)) ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Gets a value and returns. If successful, return 0. If there is an error,
|
/* Gets a value and returns. Can panic. */
|
||||||
* returns -1 for bad ds, -2 for bad key */
|
Janet janet_get(Janet ds, Janet key) {
|
||||||
int janet_get(Janet ds, Janet key, Janet *out) {
|
|
||||||
Janet value;
|
Janet value;
|
||||||
switch (janet_type(ds)) {
|
switch (janet_type(ds)) {
|
||||||
default:
|
default:
|
||||||
return -1;
|
janet_panicf("get: expected %T, got %v", JANET_TFLAG_LENGTHABLE, ds);
|
||||||
|
value = janet_wrap_nil();
|
||||||
|
break;
|
||||||
case JANET_STRUCT:
|
case JANET_STRUCT:
|
||||||
value = janet_struct_get(janet_unwrap_struct(ds), key);
|
value = janet_struct_get(janet_unwrap_struct(ds), key);
|
||||||
break;
|
break;
|
||||||
@ -162,7 +163,8 @@ int janet_get(Janet ds, Janet key, Janet *out) {
|
|||||||
{
|
{
|
||||||
JanetArray *array = janet_unwrap_array(ds);
|
JanetArray *array = janet_unwrap_array(ds);
|
||||||
int32_t index;
|
int32_t index;
|
||||||
if (!janet_checkint(key)) return -2;
|
if (!janet_checkint(key))
|
||||||
|
janet_panic("expected integer key");
|
||||||
index = janet_unwrap_integer(key);
|
index = janet_unwrap_integer(key);
|
||||||
if (index < 0 || index >= array->count) {
|
if (index < 0 || index >= array->count) {
|
||||||
value = janet_wrap_nil();
|
value = janet_wrap_nil();
|
||||||
@ -175,10 +177,10 @@ int janet_get(Janet ds, Janet key, Janet *out) {
|
|||||||
{
|
{
|
||||||
const Janet *tuple = janet_unwrap_tuple(ds);
|
const Janet *tuple = janet_unwrap_tuple(ds);
|
||||||
int32_t index;
|
int32_t index;
|
||||||
if (!janet_checkint(key)) return -2;
|
if (!janet_checkint(key))
|
||||||
|
janet_panic("expected integer key");
|
||||||
index = janet_unwrap_integer(key);
|
index = janet_unwrap_integer(key);
|
||||||
if (index < 0 || index >= janet_tuple_length(tuple)) {
|
if (index < 0 || index >= janet_tuple_length(tuple)) {
|
||||||
/*vm_throw("index out of bounds");*/
|
|
||||||
value = janet_wrap_nil();
|
value = janet_wrap_nil();
|
||||||
} else {
|
} else {
|
||||||
value = tuple[index];
|
value = tuple[index];
|
||||||
@ -189,7 +191,8 @@ int janet_get(Janet ds, Janet key, Janet *out) {
|
|||||||
{
|
{
|
||||||
JanetBuffer *buffer = janet_unwrap_buffer(ds);
|
JanetBuffer *buffer = janet_unwrap_buffer(ds);
|
||||||
int32_t index;
|
int32_t index;
|
||||||
if (!janet_checkint(key)) return -2;
|
if (!janet_checkint(key))
|
||||||
|
janet_panic("expected integer key");
|
||||||
index = janet_unwrap_integer(key);
|
index = janet_unwrap_integer(key);
|
||||||
if (index < 0 || index >= buffer->count) {
|
if (index < 0 || index >= buffer->count) {
|
||||||
value = janet_wrap_nil();
|
value = janet_wrap_nil();
|
||||||
@ -204,7 +207,8 @@ int janet_get(Janet ds, Janet key, Janet *out) {
|
|||||||
{
|
{
|
||||||
const uint8_t *str = janet_unwrap_string(ds);
|
const uint8_t *str = janet_unwrap_string(ds);
|
||||||
int32_t index;
|
int32_t index;
|
||||||
if (!janet_checkint(key)) return -2;
|
if (!janet_checkint(key))
|
||||||
|
janet_panic("expected integer key");
|
||||||
index = janet_unwrap_integer(key);
|
index = janet_unwrap_integer(key);
|
||||||
if (index < 0 || index >= janet_string_length(str)) {
|
if (index < 0 || index >= janet_string_length(str)) {
|
||||||
value = janet_wrap_nil();
|
value = janet_wrap_nil();
|
||||||
@ -214,17 +218,17 @@ int janet_get(Janet ds, Janet key, Janet *out) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*out = value;
|
return value;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int janet_getindex(Janet ds, int32_t index, Janet *out) {
|
Janet janet_getindex(Janet ds, int32_t index) {
|
||||||
Janet value;
|
Janet value;
|
||||||
if (index < 0)
|
if (index < 0) janet_panic("expected non-negative index");
|
||||||
return -2;
|
|
||||||
switch (janet_type(ds)) {
|
switch (janet_type(ds)) {
|
||||||
default:
|
default:
|
||||||
return -1;
|
janet_panicf("get: expected %T, got %v", JANET_TFLAG_LENGTHABLE, ds);
|
||||||
|
value = janet_wrap_nil();
|
||||||
|
break;
|
||||||
case JANET_STRING:
|
case JANET_STRING:
|
||||||
case JANET_SYMBOL:
|
case JANET_SYMBOL:
|
||||||
case JANET_KEYWORD:
|
case JANET_KEYWORD:
|
||||||
@ -262,44 +266,37 @@ int janet_getindex(Janet ds, int32_t index, Janet *out) {
|
|||||||
value = janet_struct_get(janet_unwrap_struct(ds), janet_wrap_integer(index));
|
value = janet_struct_get(janet_unwrap_struct(ds), janet_wrap_integer(index));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*out = value;
|
return value;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int janet_length(Janet x, int32_t *out) {
|
int32_t janet_length(Janet x) {
|
||||||
int32_t len;
|
|
||||||
switch (janet_type(x)) {
|
switch (janet_type(x)) {
|
||||||
default:
|
default:
|
||||||
return -1;
|
janet_panicf("expected %T, got %v", JANET_TFLAG_LENGTHABLE, x);
|
||||||
|
return 0;
|
||||||
case JANET_STRING:
|
case JANET_STRING:
|
||||||
case JANET_SYMBOL:
|
case JANET_SYMBOL:
|
||||||
case JANET_KEYWORD:
|
case JANET_KEYWORD:
|
||||||
len = janet_string_length(janet_unwrap_string(x));
|
return janet_string_length(janet_unwrap_string(x));
|
||||||
break;
|
|
||||||
case JANET_ARRAY:
|
case JANET_ARRAY:
|
||||||
len = janet_unwrap_array(x)->count;
|
return janet_unwrap_array(x)->count;
|
||||||
break;
|
|
||||||
case JANET_BUFFER:
|
case JANET_BUFFER:
|
||||||
len = janet_unwrap_buffer(x)->count;
|
return janet_unwrap_buffer(x)->count;
|
||||||
break;
|
|
||||||
case JANET_TUPLE:
|
case JANET_TUPLE:
|
||||||
len = janet_tuple_length(janet_unwrap_tuple(x));
|
return janet_tuple_length(janet_unwrap_tuple(x));
|
||||||
break;
|
|
||||||
case JANET_STRUCT:
|
case JANET_STRUCT:
|
||||||
len = janet_struct_length(janet_unwrap_struct(x));
|
return janet_struct_length(janet_unwrap_struct(x));
|
||||||
break;
|
|
||||||
case JANET_TABLE:
|
case JANET_TABLE:
|
||||||
len = janet_unwrap_table(x)->count;
|
return janet_unwrap_table(x)->count;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
*out = len;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int janet_putindex(Janet ds, int32_t index, Janet value) {
|
void janet_putindex(Janet ds, int32_t index, Janet value) {
|
||||||
switch (janet_type(ds)) {
|
switch (janet_type(ds)) {
|
||||||
default:
|
default:
|
||||||
return -1;
|
janet_panicf("expected %T, got %v",
|
||||||
|
JANET_TFLAG_ARRAY | JANET_TFLAG_BUFFER | JANET_TFLAG_TABLE, ds);
|
||||||
|
break;
|
||||||
case JANET_ARRAY:
|
case JANET_ARRAY:
|
||||||
{
|
{
|
||||||
JanetArray *array = janet_unwrap_array(ds);
|
JanetArray *array = janet_unwrap_array(ds);
|
||||||
@ -313,7 +310,8 @@ int janet_putindex(Janet ds, int32_t index, Janet value) {
|
|||||||
case JANET_BUFFER:
|
case JANET_BUFFER:
|
||||||
{
|
{
|
||||||
JanetBuffer *buffer = janet_unwrap_buffer(ds);
|
JanetBuffer *buffer = janet_unwrap_buffer(ds);
|
||||||
if (!janet_checkint(value)) return -3;
|
if (!janet_checkint(value))
|
||||||
|
janet_panicf("can only put integers in buffers, got %v", value);
|
||||||
if (index >= buffer->count) {
|
if (index >= buffer->count) {
|
||||||
janet_buffer_ensure(buffer, index + 1, 2);
|
janet_buffer_ensure(buffer, index + 1, 2);
|
||||||
buffer->count = index + 1;
|
buffer->count = index + 1;
|
||||||
@ -328,20 +326,21 @@ int janet_putindex(Janet ds, int32_t index, Janet value) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int janet_put(Janet ds, Janet key, Janet value) {
|
void janet_put(Janet ds, Janet key, Janet value) {
|
||||||
switch (janet_type(ds)) {
|
switch (janet_type(ds)) {
|
||||||
default:
|
default:
|
||||||
return -1;
|
janet_panicf("expected %T, got %v",
|
||||||
|
JANET_TFLAG_ARRAY | JANET_TFLAG_BUFFER | JANET_TFLAG_TABLE, ds);
|
||||||
|
break;
|
||||||
case JANET_ARRAY:
|
case JANET_ARRAY:
|
||||||
{
|
{
|
||||||
int32_t index;
|
int32_t index;
|
||||||
JanetArray *array = janet_unwrap_array(ds);
|
JanetArray *array = janet_unwrap_array(ds);
|
||||||
if (!janet_checkint(key)) return -2;
|
if (!janet_checkint(key)) janet_panicf("expected integer key, got %v", key);
|
||||||
index = janet_unwrap_integer(key);
|
index = janet_unwrap_integer(key);
|
||||||
if (index < 0 || index == INT32_MAX) return -2;
|
if (index < 0 || index == INT32_MAX) janet_panicf("bad integer key, got %v", key);
|
||||||
if (index >= array->count) {
|
if (index >= array->count) {
|
||||||
janet_array_setcount(array, index + 1);
|
janet_array_setcount(array, index + 1);
|
||||||
}
|
}
|
||||||
@ -352,10 +351,11 @@ int janet_put(Janet ds, Janet key, Janet value) {
|
|||||||
{
|
{
|
||||||
int32_t index;
|
int32_t index;
|
||||||
JanetBuffer *buffer = janet_unwrap_buffer(ds);
|
JanetBuffer *buffer = janet_unwrap_buffer(ds);
|
||||||
if (!janet_checkint(key)) return -2;
|
if (!janet_checkint(key)) janet_panicf("expected integer key, got %v", key);
|
||||||
index = janet_unwrap_integer(key);
|
index = janet_unwrap_integer(key);
|
||||||
if (index < 0 || index == INT32_MAX) return -2;
|
if (index < 0 || index == INT32_MAX) janet_panicf("bad integer key, got %v", key);
|
||||||
if (!janet_checkint(value)) return -3;
|
if (!janet_checkint(value))
|
||||||
|
janet_panicf("can only put integers in buffers, got %v", value);
|
||||||
if (index >= buffer->count) {
|
if (index >= buffer->count) {
|
||||||
janet_buffer_setcount(buffer, index + 1);
|
janet_buffer_setcount(buffer, index + 1);
|
||||||
}
|
}
|
||||||
@ -366,5 +366,4 @@ int janet_put(Janet ds, Janet key, Janet value) {
|
|||||||
janet_table_put(janet_unwrap_table(ds), key, value);
|
janet_table_put(janet_unwrap_table(ds), key, value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
177
src/core/vm.c
177
src/core/vm.c
@ -162,16 +162,14 @@ static void *op_lookup[255] = {
|
|||||||
#define vm_assert(cond, e) do {if (!(cond)) vm_throw((e)); } while (0)
|
#define vm_assert(cond, e) do {if (!(cond)) vm_throw((e)); } while (0)
|
||||||
#define vm_assert_type(X, T) do { \
|
#define vm_assert_type(X, T) do { \
|
||||||
if (!(janet_checktype((X), (T)))) { \
|
if (!(janet_checktype((X), (T)))) { \
|
||||||
expected_types = 1 << (T); \
|
vm_commit(); \
|
||||||
retreg = (X); \
|
janet_panicf("expected %T, got %t", (1 << (T)), (X)); \
|
||||||
goto vm_type_error; \
|
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define vm_assert_types(X, TS) do { \
|
#define vm_assert_types(X, TS) do { \
|
||||||
if (!(janet_checktypes((X), (TS)))) { \
|
if (!(janet_checktypes((X), (TS)))) { \
|
||||||
expected_types = (TS); \
|
vm_commit(); \
|
||||||
retreg = (X); \
|
janet_panicf("expected %T, got %t", (TS), (X)); \
|
||||||
goto vm_type_error; \
|
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@ -223,14 +221,13 @@ static void *op_lookup[255] = {
|
|||||||
|
|
||||||
/* Call a non function type */
|
/* Call a non function type */
|
||||||
static Janet call_nonfn(JanetFiber *fiber, Janet callee) {
|
static Janet call_nonfn(JanetFiber *fiber, Janet callee) {
|
||||||
int status;
|
|
||||||
int32_t argn = fiber->stacktop - fiber->stackstart;
|
int32_t argn = fiber->stacktop - fiber->stackstart;
|
||||||
Janet ds, key, ret;
|
Janet ds, key;
|
||||||
if (!janet_checktypes(callee, JANET_TFLAG_FUNCLIKE)) {
|
if (!janet_checktypes(callee, JANET_TFLAG_FUNCLIKE)) {
|
||||||
janet_panicf("attempted to called %v, expected %t", callee,
|
janet_panicf("attempted to call %v, expected %T", callee,
|
||||||
JANET_TFLAG_CALLABLE);
|
JANET_TFLAG_CALLABLE);
|
||||||
}
|
}
|
||||||
if (argn != 1) janet_panicf("%v called with arity %d, expected 1", argn);
|
if (argn != 1) janet_panicf("%v called with arity %d, expected 1", callee, argn);
|
||||||
if (janet_checktypes(callee, JANET_TFLAG_INDEXED | JANET_TFLAG_DICTIONARY)) {
|
if (janet_checktypes(callee, JANET_TFLAG_INDEXED | JANET_TFLAG_DICTIONARY)) {
|
||||||
ds = callee;
|
ds = callee;
|
||||||
key = fiber->data[fiber->stackstart];
|
key = fiber->data[fiber->stackstart];
|
||||||
@ -239,13 +236,7 @@ static Janet call_nonfn(JanetFiber *fiber, Janet callee) {
|
|||||||
key = callee;
|
key = callee;
|
||||||
}
|
}
|
||||||
fiber->stacktop = fiber->stackstart;
|
fiber->stacktop = fiber->stackstart;
|
||||||
status = janet_get(ds, key, &ret);
|
return janet_get(ds, key);
|
||||||
if (status == -2) {
|
|
||||||
janet_panic("expected integer key");
|
|
||||||
} else if (status == -1) {
|
|
||||||
janet_panic("expected table or struct");
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Interpreter main loop */
|
/* Interpreter main loop */
|
||||||
@ -257,13 +248,6 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
register JanetFunction *func;
|
register JanetFunction *func;
|
||||||
vm_restore();
|
vm_restore();
|
||||||
|
|
||||||
/* Keep in mind the garbage collector cannot see this value.
|
|
||||||
* Values stored here should be used immediately */
|
|
||||||
Janet retreg;
|
|
||||||
|
|
||||||
/* Expected types on type error */
|
|
||||||
uint16_t expected_types;
|
|
||||||
|
|
||||||
/* Only should be hit if the fiber is either waiting for a child, or
|
/* Only should be hit if the fiber is either waiting for a child, or
|
||||||
* waiting to be resumed. In those cases, use input and increment pc. We
|
* waiting to be resumed. In those cases, use input and increment pc. We
|
||||||
* DO NOT use input when resuming a fiber that has been interrupted at a
|
* DO NOT use input when resuming a fiber that has been interrupted at a
|
||||||
@ -292,22 +276,31 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
vm_pcnext();
|
vm_pcnext();
|
||||||
|
|
||||||
VM_OP(JOP_ERROR)
|
VM_OP(JOP_ERROR)
|
||||||
janet_panicv(stack[A]);
|
vm_return(JANET_SIGNAL_ERROR, stack[A]);
|
||||||
vm_next(); /* pacify compiler warnings */
|
|
||||||
|
|
||||||
VM_OP(JOP_TYPECHECK)
|
VM_OP(JOP_TYPECHECK)
|
||||||
if (!janet_checktypes(stack[A], E)) {
|
vm_assert_types(stack[A], E);
|
||||||
janet_panicf("expected %T, got %t", E, stack[A]);
|
|
||||||
}
|
|
||||||
vm_pcnext();
|
vm_pcnext();
|
||||||
|
|
||||||
VM_OP(JOP_RETURN)
|
VM_OP(JOP_RETURN)
|
||||||
retreg = stack[D];
|
{
|
||||||
goto vm_handle_return;
|
Janet retval = stack[D];
|
||||||
|
janet_fiber_popframe(fiber);
|
||||||
|
if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, retval);
|
||||||
|
vm_restore();
|
||||||
|
stack[A] = retval;
|
||||||
|
vm_checkgc_pcnext();
|
||||||
|
}
|
||||||
|
|
||||||
VM_OP(JOP_RETURN_NIL)
|
VM_OP(JOP_RETURN_NIL)
|
||||||
retreg = janet_wrap_nil();
|
{
|
||||||
goto vm_handle_return;
|
Janet retval = janet_wrap_nil();
|
||||||
|
janet_fiber_popframe(fiber);
|
||||||
|
if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, retval);
|
||||||
|
vm_restore();
|
||||||
|
stack[A] = retval;
|
||||||
|
vm_checkgc_pcnext();
|
||||||
|
}
|
||||||
|
|
||||||
VM_OP(JOP_ADD_IMMEDIATE)
|
VM_OP(JOP_ADD_IMMEDIATE)
|
||||||
vm_binop_immediate(+);
|
vm_binop_immediate(+);
|
||||||
@ -555,9 +548,7 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
if (janet_indexed_view(stack[D], &vals, &len)) {
|
if (janet_indexed_view(stack[D], &vals, &len)) {
|
||||||
janet_fiber_pushn(fiber, vals, len);
|
janet_fiber_pushn(fiber, vals, len);
|
||||||
} else {
|
} else {
|
||||||
retreg = stack[D];
|
janet_panicf("expected %T, got %t", JANET_TFLAG_INDEXED, stack[D]);
|
||||||
expected_types = JANET_TFLAG_INDEXED;
|
|
||||||
goto vm_type_error;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stack = fiber->data + fiber->frame;
|
stack = fiber->data + fiber->frame;
|
||||||
@ -582,12 +573,12 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
vm_checkgc_next();
|
vm_checkgc_next();
|
||||||
} else if (janet_checktype(callee, JANET_CFUNCTION)) {
|
} else if (janet_checktype(callee, JANET_CFUNCTION)) {
|
||||||
JanetArgs args;
|
JanetArgs args;
|
||||||
|
Janet retreg = janet_wrap_nil();
|
||||||
|
vm_commit();
|
||||||
args.n = fiber->stacktop - fiber->stackstart;
|
args.n = fiber->stacktop - fiber->stackstart;
|
||||||
janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee));
|
janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee));
|
||||||
retreg = janet_wrap_nil();
|
|
||||||
args.v = fiber->data + fiber->frame;
|
args.v = fiber->data + fiber->frame;
|
||||||
args.ret = &retreg;
|
args.ret = &retreg;
|
||||||
vm_commit();
|
|
||||||
if (janet_unwrap_cfunction(callee)(args)) janet_panicv(retreg);
|
if (janet_unwrap_cfunction(callee)(args)) janet_panicv(retreg);
|
||||||
janet_fiber_popframe(fiber);
|
janet_fiber_popframe(fiber);
|
||||||
if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, retreg);
|
if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, retreg);
|
||||||
@ -614,14 +605,15 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
stack = fiber->data + fiber->frame;
|
stack = fiber->data + fiber->frame;
|
||||||
pc = func->def->bytecode;
|
pc = func->def->bytecode;
|
||||||
vm_checkgc_next();
|
vm_checkgc_next();
|
||||||
} else if (janet_checktype(callee, JANET_CFUNCTION)) {
|
} else {
|
||||||
|
Janet retreg = janet_wrap_nil();
|
||||||
|
if (janet_checktype(callee, JANET_CFUNCTION)) {
|
||||||
JanetArgs args;
|
JanetArgs args;
|
||||||
|
vm_commit();
|
||||||
args.n = fiber->stacktop - fiber->stackstart;
|
args.n = fiber->stacktop - fiber->stackstart;
|
||||||
janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee));
|
janet_fiber_cframe(fiber, janet_unwrap_cfunction(callee));
|
||||||
retreg = janet_wrap_nil();
|
|
||||||
args.v = fiber->data + fiber->frame;
|
args.v = fiber->data + fiber->frame;
|
||||||
args.ret = &retreg;
|
args.ret = &retreg;
|
||||||
vm_commit();
|
|
||||||
if (janet_unwrap_cfunction(callee)(args))
|
if (janet_unwrap_cfunction(callee)(args))
|
||||||
vm_return(JANET_SIGNAL_ERROR, retreg);
|
vm_return(JANET_SIGNAL_ERROR, retreg);
|
||||||
janet_fiber_popframe(fiber);
|
janet_fiber_popframe(fiber);
|
||||||
@ -629,15 +621,18 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
vm_commit();
|
vm_commit();
|
||||||
retreg = call_nonfn(fiber, callee);
|
retreg = call_nonfn(fiber, callee);
|
||||||
}
|
}
|
||||||
/* Make it a tail call */
|
|
||||||
janet_fiber_popframe(fiber);
|
janet_fiber_popframe(fiber);
|
||||||
if (fiber->frame == 0)
|
if (fiber->frame == 0)
|
||||||
vm_return(JANET_SIGNAL_OK, retreg);
|
vm_return(JANET_SIGNAL_OK, retreg);
|
||||||
goto vm_reset;
|
vm_restore();
|
||||||
|
stack[A] = retreg;
|
||||||
|
vm_checkgc_pcnext();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VM_OP(JOP_RESUME)
|
VM_OP(JOP_RESUME)
|
||||||
{
|
{
|
||||||
|
Janet retreg;
|
||||||
vm_assert_type(stack[B], JANET_FIBER);
|
vm_assert_type(stack[B], JANET_FIBER);
|
||||||
JanetFiber *child = janet_unwrap_fiber(stack[B]);
|
JanetFiber *child = janet_unwrap_fiber(stack[B]);
|
||||||
fiber->child = child;
|
fiber->child = child;
|
||||||
@ -658,78 +653,24 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VM_OP(JOP_PUT)
|
VM_OP(JOP_PUT)
|
||||||
{
|
janet_put(stack[A], stack[B], stack[C]);
|
||||||
Janet ds = stack[A];
|
|
||||||
Janet key = stack[B];
|
|
||||||
Janet value = stack[C];
|
|
||||||
int status = janet_put(ds, key, value);
|
|
||||||
if (status == -1) {
|
|
||||||
expected_types = JANET_TFLAG_ARRAY | JANET_TFLAG_BUFFER | JANET_TFLAG_TABLE;
|
|
||||||
retreg = ds;
|
|
||||||
goto vm_type_error;
|
|
||||||
} else if (status == -2) {
|
|
||||||
vm_throw("expected integer key for data structure");
|
|
||||||
} else if (status == -3) {
|
|
||||||
vm_throw("expected integer value for data structure");
|
|
||||||
}
|
|
||||||
vm_checkgc_pcnext();
|
vm_checkgc_pcnext();
|
||||||
}
|
|
||||||
|
|
||||||
VM_OP(JOP_PUT_INDEX)
|
VM_OP(JOP_PUT_INDEX)
|
||||||
{
|
janet_putindex(stack[A], C, stack[B]);
|
||||||
Janet ds = stack[A];
|
|
||||||
Janet value = stack[B];
|
|
||||||
int32_t index = (int32_t)C;
|
|
||||||
int status = janet_putindex(ds, index, value);
|
|
||||||
if (status == -1) {
|
|
||||||
expected_types = JANET_TFLAG_ARRAY | JANET_TFLAG_BUFFER | JANET_TFLAG_TABLE;
|
|
||||||
retreg = ds;
|
|
||||||
goto vm_type_error;
|
|
||||||
} else if (status == -3) {
|
|
||||||
vm_throw("expected integer value for data structure");
|
|
||||||
}
|
|
||||||
vm_checkgc_pcnext();
|
vm_checkgc_pcnext();
|
||||||
}
|
|
||||||
|
|
||||||
VM_OP(JOP_GET)
|
VM_OP(JOP_GET)
|
||||||
{
|
stack[A] = janet_get(stack[B], stack[C]);
|
||||||
Janet ds = stack[B];
|
|
||||||
Janet key = stack[C];
|
|
||||||
int status = janet_get(ds, key, stack + A);
|
|
||||||
if (status == -1) {
|
|
||||||
expected_types = JANET_TFLAG_LENGTHABLE;
|
|
||||||
retreg = ds;
|
|
||||||
goto vm_type_error;
|
|
||||||
} else if (status == -2) {
|
|
||||||
vm_throw("expected integer key for data structure");
|
|
||||||
}
|
|
||||||
vm_pcnext();
|
vm_pcnext();
|
||||||
}
|
|
||||||
|
|
||||||
VM_OP(JOP_GET_INDEX)
|
VM_OP(JOP_GET_INDEX)
|
||||||
{
|
stack[A] = janet_getindex(stack[B], C);
|
||||||
Janet ds = stack[B];
|
|
||||||
int32_t index = C;
|
|
||||||
if (janet_getindex(ds, index, stack + A)) {
|
|
||||||
expected_types = JANET_TFLAG_LENGTHABLE;
|
|
||||||
retreg = ds;
|
|
||||||
goto vm_type_error;
|
|
||||||
}
|
|
||||||
vm_pcnext();
|
vm_pcnext();
|
||||||
}
|
|
||||||
|
|
||||||
VM_OP(JOP_LENGTH)
|
VM_OP(JOP_LENGTH)
|
||||||
{
|
stack[A] = janet_wrap_integer(janet_length(stack[E]));
|
||||||
Janet x = stack[E];
|
|
||||||
int32_t len;
|
|
||||||
if (janet_length(x, &len)) {
|
|
||||||
expected_types = JANET_TFLAG_LENGTHABLE;
|
|
||||||
retreg = x;
|
|
||||||
goto vm_type_error;
|
|
||||||
}
|
|
||||||
stack[A] = janet_wrap_integer(len);
|
|
||||||
vm_pcnext();
|
vm_pcnext();
|
||||||
}
|
|
||||||
|
|
||||||
VM_OP(JOP_MAKE_ARRAY)
|
VM_OP(JOP_MAKE_ARRAY)
|
||||||
{
|
{
|
||||||
@ -803,38 +744,6 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in) {
|
|||||||
vm_checkgc_pcnext();
|
vm_checkgc_pcnext();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle returning from stack frame. Expect return value in retreg */
|
|
||||||
vm_handle_return:
|
|
||||||
{
|
|
||||||
janet_fiber_popframe(fiber);
|
|
||||||
if (fiber->frame == 0) vm_return(JANET_SIGNAL_OK, retreg);
|
|
||||||
goto vm_reset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle type errors. The found type is the type of retreg,
|
|
||||||
* the expected types are in the expected_types field. */
|
|
||||||
vm_type_error:
|
|
||||||
{
|
|
||||||
JanetBuffer errbuf;
|
|
||||||
const uint8_t *message;
|
|
||||||
janet_buffer_init(&errbuf, 10);
|
|
||||||
janet_buffer_push_cstring(&errbuf, "expected ");
|
|
||||||
janet_buffer_push_types(&errbuf, expected_types);
|
|
||||||
janet_buffer_push_cstring(&errbuf, ", got ");
|
|
||||||
janet_buffer_push_cstring(&errbuf, janet_type_names[janet_type(retreg)]);
|
|
||||||
message = janet_string(errbuf.data, errbuf.count);
|
|
||||||
janet_buffer_deinit(&errbuf);
|
|
||||||
janet_panics(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset state of machine */
|
|
||||||
vm_reset:
|
|
||||||
{
|
|
||||||
vm_restore();
|
|
||||||
stack[A] = retreg;
|
|
||||||
vm_checkgc_pcnext();
|
|
||||||
}
|
|
||||||
|
|
||||||
VM_END()
|
VM_END()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1094,11 +1094,11 @@ JANET_API int32_t janet_hash(Janet x);
|
|||||||
JANET_API int janet_compare(Janet x, Janet y);
|
JANET_API int janet_compare(Janet x, Janet y);
|
||||||
JANET_API int janet_cstrcmp(const uint8_t *str, const char *other);
|
JANET_API int janet_cstrcmp(const uint8_t *str, const char *other);
|
||||||
JANET_API JanetBuffer *janet_pretty(JanetBuffer *buffer, int depth, Janet x);
|
JANET_API JanetBuffer *janet_pretty(JanetBuffer *buffer, int depth, Janet x);
|
||||||
JANET_API int janet_get(Janet ds, Janet key, Janet *out);
|
JANET_API Janet janet_get(Janet ds, Janet key);
|
||||||
JANET_API int janet_getindex(Janet ds, int32_t index, Janet *out);
|
JANET_API Janet janet_getindex(Janet ds, int32_t index);
|
||||||
JANET_API int janet_length(Janet x, int32_t *out);
|
JANET_API int32_t janet_length(Janet x);
|
||||||
JANET_API int janet_put(Janet ds, Janet key, Janet value);
|
JANET_API void janet_put(Janet ds, Janet key, Janet value);
|
||||||
JANET_API int janet_putindex(Janet ds, int32_t index, Janet value);
|
JANET_API void janet_putindex(Janet ds, int32_t index, Janet value);
|
||||||
JANET_API void janet_inspect(Janet x);
|
JANET_API void janet_inspect(Janet x);
|
||||||
|
|
||||||
/* VM functions */
|
/* VM functions */
|
||||||
@ -1132,7 +1132,7 @@ JANET_API int janet_typeabstract_err(JanetArgs args, int32_t n, const JanetAbstr
|
|||||||
JANET_API void janet_panicv(Janet message);
|
JANET_API void janet_panicv(Janet message);
|
||||||
JANET_API void janet_panic(const char *message);
|
JANET_API void janet_panic(const char *message);
|
||||||
JANET_API void janet_panics(const uint8_t *message);
|
JANET_API void janet_panics(const uint8_t *message);
|
||||||
#define janet_panicf(message, ...) janet_panics(janet_formatc(message, __VA_ARGS__))
|
#define janet_panicf(...) janet_panics(janet_formatc(__VA_ARGS__))
|
||||||
JANET_API void janet_panic_type(Janet x, int32_t n, int expected);
|
JANET_API void janet_panic_type(Janet x, int32_t n, int expected);
|
||||||
|
|
||||||
/* Helpers for writing modules */
|
/* Helpers for writing modules */
|
||||||
|
@ -110,5 +110,6 @@
|
|||||||
(assert (= 2 (@{:ok 2} :ok)) "calling table")
|
(assert (= 2 (@{:ok 2} :ok)) "calling table")
|
||||||
(assert (= :bad (try (@{:ok 2} :ok :no) ([err] :bad))) "calling table too many arguments")
|
(assert (= :bad (try (@{:ok 2} :ok :no) ([err] :bad))) "calling table too many arguments")
|
||||||
(assert (= :bad (try (:ok @{:ok 2} :no) ([err] :bad))) "calling keyword too many arguments")
|
(assert (= :bad (try (:ok @{:ok 2} :no) ([err] :bad))) "calling keyword too many arguments")
|
||||||
|
(assert (= :oops (try (1 1) ([err] :oops))) "calling number fails")
|
||||||
|
|
||||||
(end-suite)
|
(end-suite)
|
||||||
|
Loading…
Reference in New Issue
Block a user