1
0
mirror of https://github.com/janet-lang/janet synced 2024-12-27 00:40:26 +00:00

janet_try macro and janet_restore function.

This allows catching panics without using pcall.
This commit is contained in:
Calvin Rose 2020-09-19 18:47:47 -05:00
parent c455bdad11
commit d1f0a13ddc
3 changed files with 52 additions and 46 deletions

View File

@ -1315,8 +1315,25 @@ static JanetSignal janet_check_can_resume(JanetFiber *fiber, Janet *out) {
return JANET_SIGNAL_OK; return JANET_SIGNAL_OK;
} }
void janet_try_init(JanetTryState *state) {
state->stackn = janet_vm_stackn++;
state->gc_handle = janet_vm_gc_suspend;
state->vm_fiber = janet_vm_fiber;
state->vm_jmp_buf = janet_vm_jmp_buf;
state->vm_return_reg = janet_vm_return_reg;
janet_vm_return_reg = &(state->payload);
janet_vm_jmp_buf = &(state->buf);
}
void janet_restore(JanetTryState *state) {
janet_vm_stackn = state->stackn;
janet_vm_gc_suspend = state->gc_handle;
janet_vm_fiber = state->vm_fiber;
janet_vm_jmp_buf = state->vm_jmp_buf;
janet_vm_return_reg = state->vm_return_reg;
}
static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *out) { static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *out) {
jmp_buf buf;
JanetFiberStatus old_status = janet_fiber_status(fiber); JanetFiberStatus old_status = janet_fiber_status(fiber);
@ -1349,45 +1366,23 @@ static JanetSignal janet_continue_no_check(JanetFiber *fiber, Janet in, Janet *o
} }
/* Save global state */ /* Save global state */
int32_t oldn = janet_vm_stackn++; JanetTryState tstate;
int handle = janet_vm_gc_suspend; JanetSignal signal = janet_try(&tstate);
JanetFiber *old_vm_fiber = janet_vm_fiber; if (!signal) {
jmp_buf *old_vm_jmp_buf = janet_vm_jmp_buf; /* Normal setup */
Janet *old_vm_return_reg = janet_vm_return_reg;
/* Setup fiber */
if (janet_vm_root_fiber == NULL) janet_vm_root_fiber = fiber; if (janet_vm_root_fiber == NULL) janet_vm_root_fiber = fiber;
janet_vm_fiber = fiber; janet_vm_fiber = fiber;
janet_gcroot(janet_wrap_fiber(fiber)); janet_gcroot(janet_wrap_fiber(fiber));
janet_fiber_set_status(fiber, JANET_STATUS_ALIVE); janet_fiber_set_status(fiber, JANET_STATUS_ALIVE);
janet_vm_return_reg = out;
janet_vm_jmp_buf = &buf;
/* Run loop */
JanetSignal signal;
int jmpsig;
#if defined(JANET_BSD) || defined(JANET_APPLE)
jmpsig = _setjmp(buf);
#else
jmpsig = setjmp(buf);
#endif
if (jmpsig) {
signal = (JanetSignal) jmpsig;
} else {
signal = run_vm(fiber, in); signal = run_vm(fiber, in);
} }
/* Tear down fiber */ /* Restore */
if (janet_vm_root_fiber == fiber) janet_vm_root_fiber = NULL;
janet_fiber_set_status(fiber, signal); janet_fiber_set_status(fiber, signal);
janet_gcunroot(janet_wrap_fiber(fiber)); janet_gcunroot(janet_wrap_fiber(fiber));
janet_restore(&tstate);
/* Restore global state */ *out = tstate.payload;
if (janet_vm_root_fiber == fiber) janet_vm_root_fiber = NULL;
janet_vm_gc_suspend = handle;
janet_vm_fiber = old_vm_fiber;
janet_vm_stackn = oldn;
janet_vm_return_reg = old_vm_return_reg;
janet_vm_jmp_buf = old_vm_jmp_buf;
return signal; return signal;
} }

View File

@ -1030,6 +1030,19 @@ struct JanetFile {
int32_t flags; int32_t flags;
}; };
/* For janet_try and janet_restore */
typedef struct {
/* old state */
int32_t stackn;
int gc_handle;
JanetFiber *vm_fiber;
jmp_buf *vm_jmp_buf;
Janet *vm_return_reg;
/* new state */
jmp_buf buf;
Janet payload;
} JanetTryState;
/* Thread types */ /* Thread types */
#ifdef JANET_THREADS #ifdef JANET_THREADS
typedef struct JanetThread JanetThread; typedef struct JanetThread JanetThread;
@ -1411,6 +1424,13 @@ JANET_API JanetBuffer *janet_pretty(JanetBuffer *buffer, int depth, int flags, J
#define JANET_HASH_KEY_SIZE 16 #define JANET_HASH_KEY_SIZE 16
JANET_API void janet_init_hash_key(uint8_t key[JANET_HASH_KEY_SIZE]); JANET_API void janet_init_hash_key(uint8_t key[JANET_HASH_KEY_SIZE]);
#endif #endif
JANET_API void janet_try_init(JanetTryState *state);
#if defined(JANET_BSD) || defined(JANET_APPLE)
#define janet_try(state) (janet_try_init(state), (JanetSignal) _setjmp((state)->buf))
#else
#define janet_try(state) (janet_try_init(state), (JanetSignal) setjmp((state)->buf))
#endif
JANET_API void janet_restore(JanetTryState *state);
JANET_API int janet_equals(Janet x, Janet y); JANET_API int janet_equals(Janet x, Janet y);
JANET_API int32_t janet_hash(Janet x); 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);

View File

@ -3,7 +3,6 @@
(var num-tests-passed 0) (var num-tests-passed 0)
(var num-tests-run 0) (var num-tests-run 0)
(var suite-num 0) (var suite-num 0)
(var numchecks 0)
(var start-time 0) (var start-time 0)
(defn assert (defn assert
@ -13,16 +12,8 @@
(++ num-tests-run) (++ num-tests-run)
(when x (++ num-tests-passed)) (when x (++ num-tests-passed))
(if x (if x
(do (xprintf stdout "\e[32m✔\e[0m %s: %v" (string e) x)
(when (= numchecks 25) (xprintf stdout "\n\e[31m✘\e[0m %s: %v" (string e) x))
(set numchecks 0)
(print))
(++ numchecks)
(file/write stdout "\e[32m✔\e[0m"))
(do
(file/write stdout "\n\e[31m✘\e[0m ")
(set numchecks 0)
(print e)))
x) x)
(defmacro assert-error (defmacro assert-error