At Wed, 26 Jul 2017 14:44:05 -0700 (PDT), Thomas Dickerson wrote:
> Looking at this code specifically:
>
> | mz_jmp_buf * volatile save, fresh;
> | save = scheme_current_thread->error_buf;
> | scheme_current_thread->error_buf = &fresh;
> |
> | if (scheme_setjmp(scheme_error_buf)) {
> | /* There was an error or continuation invocation */
> | if (scheme_jumping_to_continuation) {
> | /* It was a continuation jump */
> | scheme_longjmp(*save, 1);
> |
> | /* To block the jump, instead: scheme_clear_escape(); */
> | } else {
> | /* It was a primitive error escape */
> | }
> | } else {
> | scheme_eval_string("x", scheme_env);
> | }
> | scheme_current_thread->error_buf = save;
>
> I have questions about a few things:
> (a) Why does the example check for an error *before* calling
> `scheme_eval_string`, rather than afterward? Is this just something weird
> with
> setjmp/longjmp?
Yes, that's how setjmp() and longjmp() work. The initial call to
setjmp() always returns 0, etc.
> (b) How do I handle the "primitive error escape" branch, assuming I
> want to print a useful error message, and continue executing
> gracefully? It looks like `scheme_clear_escape` may be useful for
> preventing the exception from propagating, but I'm not sure about
> that from the documentation (or how I'd be able to capture the error
> message from the exception).
That branch corresponds to `abort-current-continuation`. If it's due to
an exception, then the exception was already printed and (probably) the
default error escape handler called `abort-current-continuation`.
Catching the value raised as an exception is not practical to do in C.
It's better to wrap up the work like `scheme_eval_string("x",
scheme_env)` in a thunk and call a Racket-implemented wrapper. Section
9.1 in "Inside Racket" shows one way to do that.
> (c) Is this style of error handling only necessary around blocks that
> are evaluating actual Racket code (via, e.g., `scheme_eval_string` or
> `scheme_dynamic_require`)? What about the
> `scheme_register_embedded_load` and `scheme_embedded_load` pair at
> the bottom of `declare_modules`? I ran my binary through the Unix
> `strings` command and the embedded data looks an awful lot like
> expanded S-expressions in plain text. Additionally, at what level of
> granularity should I structure the error handling? Does it need to be
> for *every* evaluation, individually? Or could I surround a whole
> block of evaluations with the same error handling code?
Declaring (as opposed to instantiating) a compiled module will normally
not raise an exception. Probably it's possible to construct a set of
embedded modules where there will be a declare-time error due to
conflicting or missing declarations, but I don't see how to make that
happen only sometimes.
The escape-catching pattern is needed anywhere that you don't want to
just exit/crash.
You can certainly call multiple `scheme_...` functions within a single
escape-handling block, including multiple calls to `scheme_eval_string`.
--
You received this message because you are subscribed to the Google Groups
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.