1
0
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:
Calvin Rose 2019-01-05 00:33:20 -05:00
parent cd6a7793e8
commit 5b62c8e6db
5 changed files with 115 additions and 206 deletions

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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()
} }

View File

@ -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 */

View File

@ -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)