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.

Reply via email to