[ Note to p6c: This thread is about the proposed and only partially
specified ".begin_eh"/".end_eh" directives that would specify exception
handling as a static property of a range of opcodes in a subroutine,
rather than the current dynamic approach of C<push_handler> etc. I'm
including p6c in case Lisp isn't the only language with potential issues
here. See also docs/pdds/clip/pdd23_exceptions.pod.]
On Mon, Jun 12, 2006 at 08:24:55PM -0400, Bob Rogers wrote:
> From: Chip Salzenberg <[EMAIL PROTECTED]>
> Date: Mon, 12 Jun 2006 06:54:24 -0700
>
> On Sun, Jun 11, 2006 at 11:52:14AM -0400, Bob Rogers wrote:
> > I notice the following paragraph, vintage late May, in
> > pdd23_exceptions.pod:
> >
> > A C<.begin_eh> directive marks the beginning of a span of
> > opcodes which the programmer expects to throw an exception. If
> > an exception occurs in the execution of the given opcode span,
> > Parrot will transfer control to I<LABEL>.
> >
> > I assume this means that you intend to replace the current methodology
> > of searching for an Exception_Handler object on the control stack when
> > an error is thrown with a search through sub metadata.
>
> That's the plan. The upside is that on the non-exceptional case, nothing
> at
> all needs to be done. I just couldn't see the value in making the VM
> allocate and free memory blocks on the control stack, over and over, when
> no exceptions are occurring.
>
> Yes, that's nice. The downside, though, is that you have to do more
> work when it's time to throw, but I agree that this is likely to happen
> less often, at least for most error-handling situations. (There's also
> a load-time cost, I imagine, but it can't be very large.)
I think we're seeing the same thing.
> Unfortunately, this is a step backwards from my perspective, as it is
> already problematic to use Parrot as it exists now to implement ANSI
> Common Lisp error signalling semantics, and any approach based on
> metadata (being static) will make it more so. However, I can still
> implement ANSI semantics using dynamic binding, C<pushaction>, and
> continuations that respect both (which they currently do not), though
> the result won't interoperate with error handling in the rest of Parrot.
{{ Please read the rest of the message before answering this paragraph.
It may be moot. }}
OK, maybe I don't understand CL or your implmentation strategy, but: Aren't
you planning on -compiling- the CL to PIR? When the form that does
exception handling is compiled to PIR, why can't you translate it to (among
other things) a .eh block?
Separately, what do you mean by "respecting" pushaction in the continuation
implementation?
> > How do you envision this interacting with C<pushaction>, e.g.?
> Currently,
> > it is straightforward for find_exception_handler to DTRT WRT other
> control
> > stack entries. Would the metadata also contain information about
> > C<pushaction> and such?
>
> I hadn't decided either way about C<pushaction>. Seems to me that either
> way will work though. Could you spell out a little more of what you see
> as being bad (or harder)?
>
> Actions are dynamic state that must nest properly with respect to error
> handlers. So you have to know how many actions to pop & invoke when
> unwinding the stack before invoking a given error handler. So it seems
> to me that you would also have to lexicalize actions in order to give
> find_exception_handler a clue.
Ah, well, that's fine then. In fact we are going to lexicalize actions, in
the form of an optional I<FINALLY_LABEL> on .begin_eh:
.begin_eh [ I<CATCH_LABEL> ] [ , I<FINALLY_LABEL> ]
A 'finally' label gets called on the way out of an exception block whether
or not the departure was the result of an exception. To handle the non-
exception case, I imagine PIR will just emit "call my_finally" when it
encounters the ".end_eh" directive.
On the other hand, since static exception blocks haven't been implemented
yet, it's not too late to ditch the whole change as a bad job, if that's
the right decision for Lisp and other languages. Lispers are people too. :-)
> But you can't lexicalize actions completely without removing the ability
> to invoke a closure as a cleanup action!
Not at all. It just makes you emit the call instruction yourself. For
example:
.sub example
.local pmc my_cleanup
my_cleanup = <insert expression here that would have been pushaction'd>
.begin_eh ,my_finally
# body of subroutine here
.end_eh
.return ()
my_finally:
call my_cleanup
ret
.end
The implications of throwing an exception from a 'finally' label need to be
specified clearly, of course. But once that's done, making sure that
exception handling code calls all the right 'finally' labels in the right
order is a Simple Matter Of Programming.
> Dynamic bindings in particular require runtime dynamic state (namely, the
> saved values), so there still needs to be something on the control stack
> to capture it.
I think the 'finally' feature is pretty much what you need for this.
--
Chip Salzenberg <[EMAIL PROTECTED]>