guile-devel
[Top][All Lists]
Advanced

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

Lazy catch behaviour


From: Neil Jerram
Subject: Lazy catch behaviour
Date: 11 May 2001 16:52:03 +0100
User-agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7

When documenting lazy-catch last week, I was surprised to discover
that it _does_ unwind the dynamic context back to the `lazy-catch'
before invoking the handler.  It seemed to me that, if it doesn't
unwind the stack, it would be consistent also not to unwind the
dynamic context.

Today, I discovered a weird consequence of the current behaviour,
while playing around with the evaluator traps support.  If I set a
trivial enter-frame-handler, and then enable enter-frame trapping, the
REPL goes into an infinite loop bouncing between the inside and the
outside of the `dynamic-wind' in the readline.scm implementation of
`repl-reader'.

Here's exactly what I do to see this:

guile> (set! enter-frame-handler (lambda args (write args) (newline)))
guile> (trap-enable 'enter-frame)

[Using exit-frame instead produces the same behaviour BTW:

guile> (set! exit-frame-handler (lambda args (write args) (newline)))
guile> (trap-enable 'exit-frame)
]

So the effective overall pattern is:

(lazy-catch #t
            (lambda ()
              ...
              (dynamic-wind (lambda ()
                              ;; read in-guard
                              ...)
                            (lambda ()
                              (read))
                            (lambda ()
                              ;; read out-guard
                              ...)))
            (lambda args
              (write args)
              (newline)))

What I think happens is:

1. For every frame in the evaluation of the in-guard, the enter frame
   handler is called and prints the result.  Note that the dynamic
   wind isn't yet active until the in-guard has completed.

2. Evaluation begins of the dynamic-wind thunk, but before it gets
   very far, we throw to the enter frame handler.

3. Before reaching the enter frame handler, we must invoke the
   out-guard.  The enter frame handler is called for every frame in
   the out-guard thunk.

4. Finally we get to the enter frame handler for the first frame of
   the inner thunk, which prints its args and then returns, so we wind
   back through the in-guard, calling the frame handler for every
   frame ...

5. Repeat for the next frame in the inner thunk ...

6. Somewhere in the middle of all this, readline throws an error to
   the effect that it is not reentrant.  This error is caught by the
   REPL, which then loops ...

Two things emerge from all this:

1. Is the current lazy-catch behaviour useful?  Certainly not in this
   case, and for most uses of the evaluator trap handlers that I can
   imagine.  Can anyone suggest any cases where it is positively
   useful to unwind the dynamic context before invoking the lazy catch
   handler?  I realize that we have to be careful about making sure
   that the lazy-catch is not active during the execution of its own
   handler, but couldn't we special-case that?

   On the other hand, if we don't unwind the dynamic context, a lazy
   catch handler call is basically just the same as calling the
   handler inline instead of the throw.  Could the evaluator trap
   handlers be implemented as simple procedure calls rather than
   by throwing exceptions?

2. There's a readline reentrancy bug in there somewhere.

Thoughts?

        Neil




reply via email to

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