From: Chip Salzenberg <[EMAIL PROTECTED]>
   Date: Wed, 14 Jun 2006 12:05:29 -0700

   [ 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:
   >
   > . . .
   >
   >    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. }}

In fact, it's central, and meet to be mooted (in the oldest sense of the
word.  ;-)

   OK, maybe I don't understand CL or your implmentation strategy, but:
   Aren't you planning on -compiling- the CL to PIR?

Yes, of course.

   When the form that does exception handling is compiled to PIR, why
   can't you translate it to (among other things) a .eh block?

CL handlers are functions (typically closures) that are invoked by ERROR
or SIGNAL in order to decide how to handle the condition [1].  The first
handler that effects a nonlocal exit is considered to have handled the
condition.  If no handlers bite, and the condition was signalled by
ERROR, then the debugger is entered; otherwise, SIGNAL just returns --
both still at the point the condition was signalled, with its context
intact.  Even if the condition is handled somewhere, returning to a .eh
block isn't quite correct, as then the handler body is running in the
handler's bind-time environment, rather than the dynamic environment of
the error.

   Essentially, I don't see how to implement a reasonable facsimile of
ANSI semantics without handlers-as-functions.

   In fact, I had thought that this was where the "early draft of
exceptions PDD" thread was going last April.  So I proposed essentially
the Lisp model on 29-April, but I never heard back, so I assumed that it
was considered too radical.  It would certainly cost an instruction or
two more than the current implementation to establish an error handler.

   Separately, what do you mean by "respecting" pushaction in the
   continuation implementation?

Currently, invoking a continuation will unwind the stack past actions
without invoking them, since the unwinding is implicit in the way
continuations re-establish the control stack.  The fix is not difficult,
but neither is it completely straightforward, especially as there are
other related bugs in that code.  (There is also the semantic issue of
whether an action should be invoked for a given kind of continuation; I
intend to propose [2] that the action should decide.)  So I haven't
tried to fix this one yet because I assume it would be easier to clobber
them all at once when implementing related control stack changes for
dynamic binding [2].

   > 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.

Sounds good to me.  Several questions/thoughts:

   1.  By "call", do you mean "jsr" (or "bsr" -- I don't grok the
distinction)?  I notice that your example below (which I snipped) uses
"ret" at the end of the 'finally' block, but it's not clear how that
translates into a resumption of stack-unwinding.

   2.  Since the CL features that would use this construct are
independent, I would never need to emit code that uses both.  Instead,
it would be either

        .begin_eh I<CATCH_LABEL>

or

        .begin_eh ,I<FINALLY_LABEL>

So it might be clearer to have a separate ".begin_finally" and
".end_finally" for the latter.  (But of course this is a merely a
trifling question of syntax.)

   3.  FWIW, the Scheme dynamic-wind feature requires an action to be
invoked when re-entering the context as well as leaving it.  But this is
probably not relevant, as a real Scheme implementation would probably
not need Parrot continuations or actions in any case.

   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.  
:-)

You mean -+<{gasp}>+- I can come out of my closet now?

   Seriously, I appreciate your willingness to listen to fans of
minority languages.  So far, my strategy has been to propose only
changes that I think will benefit Parrot and Perl 6 in general.  In the
future, I may need to suggest changes that are only useful for Lisp, but
I hope by that time I will have released my compiler [3], and the Parrot
world can judge them in context.

   FWIW, I confess to being of two minds about stack exception blocks,
even just considering changes from the current functionality, as opposed
to anything additional required for Lisp.  On the one hand, I can see
what you're trying to do, and it makes some sense.  On the other hand, I
wonder whether this will add a nontrivial dose of complexity for the
sake of a hard-to-measure speedup.  Note that this is not about Lisp
semantics; the complexity will still be required for Perl 6 features.

   > 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 . . .

Of course; that's much simpler than what I had in mind.  I was assuming
that C<.begin_eh> would nominate a Sub as the cleanup action, instead of
a label.  And the only reason I wanted a closure in the first place was
to retain the context, which using a label provides first-hand.

   > 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]>

I'm afraid I don't see how.  The issue is preserving dynamic binding
state when switching contexts via continuation or coroutine.  This
context switching may be done an arbitrary number of times, moving both
up and down the call stack, whereas 'finally' semantics seem to be
'fire-once-when-unwinding.'  Or is this too being generalized?

   Also, though less important, merging dynamic binding into 'finally'
means that debuggers won't be able to tell you which variables are bound
dynamically.  (Unless you add metadata to that end, but that makes
introspection more difficult; it seems much easier to have a binding
object that can be queried directly by a PIR-level debugger.)

                                        -- Bob

P.S.  This has probably already occurred to you, but at some point you
will need to tell me whether I can proceed with implementing dynamic
binding on the current implementation, or whether I should wait until
you've designed/implemented/punted static exception blocks.

================

[1]  
http://www.lispworks.com/documentation/HyperSpec/Body/m_handle.htm#handler-bind

[2]  See http://rgrjr.dyndns.org/perl/dynbind-proposal-v2.html for the
     latest draft.

[3]  At which time I will have truly left the closet.

Reply via email to