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

Re: issue EXIT-EXTENT



I think it is unfortunately the case that my original estimate

 "I think it is unlikely that the cleanup committee will
have much more to say on the issue." 

is unfortunately untrue.

I'll try to answer your questions, and hope that I can get a 
volunteer other than myself to produce a new writeup.

(1) What does "extent of an exit" mean?

An "exit" is something you can RETURN from, or that GO implicitly can
return from, or that THROW will return from. So its either a BLOCK body, a
top level form of a TAGBODY, or a CATCH.  CLtL makes it clear that "exit"s
have dynamic extent. For example, attempting to funcall the value of 

 (block frob #'(lambda () (return-from frob 3)) ) )

is an error, in that the "extent" the block  to which the return-from
returns from has elapsed since the block has been exited. On the other
hand,

(block frob (let ((a #'(lambda () (return-from frob 3)))) (funcall a )))

is not an error; the extent of the frob block has not elapsed when the
return-from is invoked.

The ambiguity only arised because of unwind-protect. (I can't think of any
other situations, although the condition proposal might introduce some
unwind-protect equivalents.)

While "exits" have dynamic extent,  the exact boundary of when that dynamic
extent ends is fuzzy, primarily because of UNWIND-PROTECT.

Given a block (block frob ...) which contains a (return-from frob ...) in
it, we normally think of (return-from frob ...) as a "instantaneous"
operation. However, if there's an UNWIND-PROTECT in between, user code an
execute between the "start" of (RETURN-FROM FROB ...) and when the (BLOCK
FROB ...) is actually exited. Is the extent of (BLOCK FROB ...) over when
(RETURN-FROM FROB ...) starts, or is it over when it ends? 

If the extent is over only when the block is exited, then the following
cases would *not* be an error:

(block nil                                              ;case 2
  (unwind-protect (return)
    (return)))

(block a                                                ;case 3
  (block b
    (unwind-protect (return-from a)
      (return-from b))))


(catch nil                                              ;case 2
  (unwind-protect (throw nil t)
    (throw nil t)))

(catch 'a                                               ;case 3
  (catch 'b
    (unwind-protect (throw 'a t)
      (throw 'b t))))