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

Issue: UNWIND-PROTECT-CLEANUP-NON-LOCAL-EXIT (Version 4)



I'm sorry I haven't had time to relay the commentary that we've come up
with here at Lucid.  Mostly we want to specify that the following situation
is an error; and in fact I think it is reasonable to signal an error:

    During the execution of the cleanup forms of an UNWIND-PROTECT a non-local
    exit to a point outside of the [dynamic] scope of the UNWIND-PROTECT, but 
    still within the dynamic scope of of the target of the original non-local 
    exit succeeds, and the original pending exit is discarded. For example, in 
    Situation 1, the pending seek for tag FOO is discarded by the second THROW
    to BAR and the value 4 is transfered to (CATCH 'BAR ...), which returns 4.
    The (CATCH 'FOO ...) then returns the 4 because its first argument has 
    returned normally. XXX is not printed.

That is, we don't want this case to "succeed", but rather to signal an error.
When we had the discussion at Fort Collins, it was just this point that I
knew moon and I agreed on, and everyone else present disagreed.  In fact,
now, there is some more argumentation based on our QLISP implementation that 
almost requires this to be "an error" at least.

The operative phrase we have come up with is that

    THROW "commits"

That is, when a THROW decides that there is a catch-tag somewhere up there
to catch it, then no intervening UNWIND-PROTECT can function like a
catch barrier.  That THROW is "committed" to unwinding the stack at least
up to the tagged point.  I think VAX/NIL or MacLisp had such a primitive 
called CATCH-BARRIER, or CATCHALL, that would stop any THROW of any tag name
whatsoever; this was considered and rejected for Common Lisp, and for
good reason.  

Thus is is OK to "extend the THROW"; meaning that when a THROW to a tag HIGH 
is executing, and some unwind-protect cleanup form executes a THROW to tag
HIGHER that is outside the dynamic scope of the catch on tag HIGH, then
that cleanup form code will:
    (1) abort it's own local processing 
    (2) indicate that the throw to tag HIGH will now be extended to HIGHER
    (3) continue with the unwinding, up to the next unwind-protect cleanup
        or to the final destination HIGHER.

What's not OK is to block a "committed" THROW.  Without this restriction,
for example, an "abort" to top-level while runnining the application evaluator
noted below would never succeed; the THROW to FOO from within the cleanup
form would serve as an effect barrier such that no throw can go past it.

      (loop
	(catch 'foo
	  (unwind-protect 
		(Run-application-evaluator)
	    (throw 'foo t))))


We have actually programmed this up, but it is not in Lucid's current
product.


-- JonL --