[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: scm_c_catch question

From: Ian Grant
Subject: Re: scm_c_catch question
Date: Sun, 17 Aug 2014 21:14:14 -0400

Hi Neil,

Sorry, I am replying to my message because I'm not on guile-devel, it seems. I'll join later.

Thanks for clarifying that. The misleading statement in the manual is just above the paragraph you quote: on it says

    Handler is invoked outside the scope of its own catch. If handler
    again throws to the same key, a new handler from further up the
    call chain is invoked.

It doesn't mention pre_unwind_handler, which implies that the statement does _not_ apply to pre_unwind_handler. So this should be amended.

But it would be more useful if there were a way to allow a throw to be aborted as I was expecting. How hard would that be to implement? If you think the semantics are in fact different, it could be given a new name, scm_c_catch_and_rethrow or something. What I want is something like BSD signals semantics, where the handler is not reset when the signal occurs.

You ask "In your code, the pre-unwind handler calls failwith() and doesn't expect it to return - so where does it jump to?"

I thought I had explained that, sorry. The call to failwith() does a C longjmp back into the CAML bytecode interpreter (i.e. back down below the call stack into caml_main). This is not a non-local exit, as far as Guile is concerned, because it is just a 'naked' C longjmp. So in that sense, the second time Guile throws an exception it is being thrown from within pre_unwind_handler.

Is there a way to implement what I want with fluids?


On Fri, Aug 15, 2014 at 6:13 PM, Ian Grant <address@hidden> wrote:
Hello Guile types,

I have been experimenting with using libguile from within another byte-code interpreter: Moscow ML. I have a version of Moscow ML with an GNU lightning interface in which I JIT compile primitives to give access to libguile functions from Standard ML.

Moscow ML uses an old version of the CAML light runtime which is a byte-code interpreter implemented in C. The CAML runtime provides exceptions implemented using a longjmp buffer.

The Moscow ML top-level REPL is implemented as a byte-code compiled ML function which is invoked by main(). What I would like to do would be to catch any unhandled Guile exceptions and re-throw them as ML exceptions so that the toplevel isn't exit'ed by an un-handled scheme exception. To this end I call the CAML main from the scm_boot_guile callback, under a scm_c_catch. This code is in the guilert.c file The only CAML'ism here is the call to failwith("message"). This does a longjump 'into the CAML exception bucket'

The problem is that after the first successful catch by the pre-unwind handler, the next Guile exception is handled by the main_handler. This is not what I expected. The manual seems to say that it is only after the main_handler is invoked, that the catch is cancelled. Is this not the right understanding? The output of the example shows this isn't what happens:

debug: main_trampoline: calling scm_c_catch(main_call,main_handler,main_pre_unwind_handler)
debug: main_call: calling caml_main
Moscow ML [Red October] 2.10
Type `quit();' to quit.
- scm_repl();
Moscow ML Guile REPL
Type `(quit)' to exit.
> (+ "ab")
debug: main_pre_unwind_handler called
! Uncaught exception:
! Fail  "Uncaught scheme exception"
- scm_repl();
Moscow ML Guile REPL
Type `(quit)' to exit.
> (+ "ab")
debug: main_handler called
debug: main_trampoline: scm_c_catch returned!

Process mosml finished

reply via email to

[Prev in Thread] Current Thread [Next in Thread]