Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Exceptions

15 views
Skip to first unread message

Dan Sugalski

unread,
Jun 21, 2003, 1:45:47 PM6/21/03
to perl6-i...@perl.org
Okay, now that we're well on our way to getting sub/method/whatever
calling down and working, I want to point us towards what I'm
thinking of for exceptions.

Exception handlers really strike me as anonymous lexically scoped
subroutines that get called with just one parameter--the exception
object. As far as the engine should be concerned, when an exception
is taken we just take a continuation with the address being the start
of the code that handles the exception. They need to get pushed on
the system stack so we can walk up it at runtime when an exception is
called looking for handlers.

I'm not yet sure whether it's worth having engine support for
specific exception type checking (that is, make it so that the engine
looks at the exception information and checks properties on the
exception handler to see whether it should even be invoked), or if we
should just leave that up to the languages that care about typed
exceptions to rethrow anything a handler can't handle. I'm leaning
towards having the exception handlers check and rethrow, as it's
easiest and leaves the most flexibility to the languages.

Once we get the last bits of the continuation/sub/method stuff nailed
down we can get this stuff going as well.
--
Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk

Piers Cawley

unread,
Jun 23, 2003, 8:53:34 AM6/23/03
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski <d...@sidhe.org> writes:

> Okay, now that we're well on our way to getting sub/method/whatever
> calling down and working, I want to point us towards what I'm thinking
> of for exceptions.
>
> Exception handlers really strike me as anonymous lexically scoped
> subroutines that get called with just one parameter--the exception
> object. As far as the engine should be concerned, when an exception is
> taken we just take a continuation with the address being the start of
> the code that handles the exception. They need to get pushed on the
> system stack so we can walk up it at runtime when an exception is
> called looking for handlers.

So, we grab another register for 'current exception continuation'?
Then when code throws an exception it just takes the exception
continuation and if that can't handle the exception it takes *its*
current exception continuation and so on up the exception chain?

Nice trick.

--
Piers

Brent Dax

unread,
Jun 24, 2003, 2:32:06 PM6/24/03
to Piers Cawley, Dan Sugalski, perl6-i...@perl.org
Piers Cawley:

Dan Sugalski <d...@sidhe.org> writes:
> Exception handlers really strike me as anonymous lexically scoped
> subroutines that get called with just one parameter--the exception
> object.

So, we grab another register for 'current exception continuation'?


Then when code throws an exception it just takes the exception
continuation and if that can't handle the exception it takes *its*
current exception continuation and so on up the exception chain?

--

I think The Plan (tm) is to attach the exception handler to system stack
frames. When an exception is thrown, we pop frames off the system stack
until we reach one with an exception handler attached. This has several
benefits:

1) It means the system stack is exactly where it should be when we call
the exception handler.

2) It automatically restores outer exception handlers when inner ones go
out of scope.


(Sorry about the formatting--I just reinstalled Windows, and I'm still
settling in here.)

--Brent Dax <bren...@cpan.org>

Dan Sugalski

unread,
Jun 24, 2003, 2:37:10 PM6/24/03
to Piers Cawley, perl6-i...@perl.org
At 8:53 AM -0400 6/23/03, Piers Cawley wrote:
>Dan Sugalski <d...@sidhe.org> writes:
>
>> Okay, now that we're well on our way to getting sub/method/whatever
>> calling down and working, I want to point us towards what I'm thinking
>> of for exceptions.
>>
>> Exception handlers really strike me as anonymous lexically scoped
>> subroutines that get called with just one parameter--the exception
>> object. As far as the engine should be concerned, when an exception is
>> taken we just take a continuation with the address being the start of
>> the code that handles the exception. They need to get pushed on the
>> system stack so we can walk up it at runtime when an exception is
>> called looking for handlers.
>
>So, we grab another register for 'current exception continuation'?

Nope. The exception goes onto the control stack. When an exception is
thrown we walk up the control stack frames until we find an exception
handler entry, at which point we invoke the continuation associated
with it, passing in the exception information. (Though we may put the
exception info out-of-band, since I can see wanting to retain all the
registers for Truly Clever exception handlers...)

Leopold Toetsch

unread,
Jun 25, 2003, 3:46:07 AM6/25/03
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski <d...@sidhe.org> wrote:
> Exception handlers really strike me as anonymous lexically scoped
> subroutines that get called with just one parameter--the exception
> object. As far as the engine should be concerned, when an exception
> is taken we just take a continuation with the address being the start
> of the code that handles the exception.

Reading through pdd06 the following is not really speced (IMHO):

Exception handlers are dynamically scoped, and any
exception handler set in a scope will be removed when that
scope is exited.

How do we remove exception handlers on scope exit. Is this done, when we
encounter a C<pop_pad> instruction? Or should the HL emit a C<clear_eh>
opcode?
As the exception handlers live on the control stack, there is not much
connection between a lexical pad being popped off and removing
exceptiion handlers in scope.

> I'm not yet sure whether it's worth having engine support for
> specific exception type checking

I think we would have:
- Exception handler = Continuation
- Exception object = a new class of some type[2]. When the system throughs
an exception, it would attach 2 properties to the exception object:
"class" - exception class, e.g. math.div_by_zero[3] or so
"text" - textual representation

The system then could check:
- does the exception handler has a matching[1] "class" property and if yes
call it, if no walk up the control stack.

[1] is wildmat(3) so its totally up to the usercode if the exception
handler gets called. If the Continuation object (the exception
handler) has a property of C<class="*"> it catches all, if its
e.g. C<class="math.*" it catches all math exceptions.
When user code wants to do it all, it could have a C<class=*>
property and another e.g. "UserClass" property for its own type
checking.

[2] e.g. a Hash where we compare hash data against the handlers
properties.

[3] Classifying all kinds of exception would need a fair amount of work.
We have:
- system exception (e.g. SIGFPE): we need signal handlers
- internal_exception(): a lot of them are probably panic()s
- user code exception: up to the HL/programmer

Yet another question: Will we have semantics of repeating a failed
instruction or continuing e.g. after a SIGFPE at bytecode level / in
C-code?

Comments welcome,
leo

Luke Palmer

unread,
Jun 25, 2003, 5:05:55 AM6/25/03
to l...@toetsch.at, d...@sidhe.org, perl6-i...@perl.org
> > I'm not yet sure whether it's worth having engine support for
> > specific exception type checking
>
> I think we would have:
> - Exception handler = Continuation
> - Exception object = a new class of some type[2]. When the system throughs
> an exception, it would attach 2 properties to the exception object:
> "class" - exception class, e.g. math.div_by_zero[3] or so
> "text" - textual representation

Well Perl 6 thinks that those should be contained within (or
generatable from) the exception object itself, not attached as
properties. But I'm sure it could emulate those properties, or vice
versa, so not a big deal.

> The system then could check:
> - does the exception handler has a matching[1] "class" property and if yes
> call it, if no walk up the control stack.

> [1] is wildmat(3) so its totally up to the usercode if the exception
> handler gets called. If the Continuation object (the exception
> handler) has a property of C<class="*"> it catches all, if its
> e.g. C<class="math.*" it catches all math exceptions.
> When user code wants to do it all, it could have a C<class=*>
> property and another e.g. "UserClass" property for its own type
> checking.

Exceptions are traditionally done using inheritance, which I think
fits the bill quite nicely (unlike most other things inheritance is
used for ;-). I'm not sure doing handling based on textual patterns
is such a good idea....

But inheritance isn't quite versatile enough for Perl. I suppose in
the tricky cases Perl could install a "universal base class" handler,
and then do its magic from the handler code. Just, er, I'm not for
exception globs.

> [2] e.g. a Hash where we compare hash data against the handlers
> properties.
>
> [3] Classifying all kinds of exception would need a fair amount of work.
> We have:
> - system exception (e.g. SIGFPE): we need signal handlers
> - internal_exception(): a lot of them are probably panic()s
> - user code exception: up to the HL/programmer
>
> Yet another question: Will we have semantics of repeating a failed
> instruction or continuing e.g. after a SIGFPE at bytecode level / in
> C-code?
>
> Comments welcome,
> leo

Luke

Benjamin Goldberg

unread,
Jun 26, 2003, 7:54:01 PM6/26/03
to perl6-i...@perl.org
Dan Sugalski wrote:
> Piers Cawley wrote:
>> Dan Sugalski <d...@sidhe.org> writes:
>>
>>> Okay, now that we're well on our way to getting
>>> sub/method/whatever calling down and working, I want to point us
>>> towards what I'm thinking of for exceptions.
>>>
>>> Exception handlers really strike me as anonymous lexically scoped
>>> subroutines that get called with just one parameter--the exception
>>> object. As far as the engine should be concerned, when an
>>> exception is taken we just take a continuation with the address
>>> being the start of the code that handles the exception. They need
>>> to get pushed on the system stack so we can walk up it at runtime
>>> when an exception is called looking for handlers.
>>
>> So, we grab another register for 'current exception continuation'?
>
> Nope. The exception goes onto the control stack. When an exception is
> thrown we walk up the control stack frames until we find an exception
> handler entry, at which point we invoke the continuation associated
> with it, passing in the exception information. (Though we may put the
> exception info out-of-band, since I can see wanting to retain all the
> registers for Truly Clever exception handlers...)

Well, how about we have throwing an exception be similar to resuming a
coroutine?

That is, we save all the context from where the exception was thrown,
and then pass that into the exception handler.

Concievably, we could then examine the exception, and maybe decide that
it was nonfatal, and resume execution from just after the place it was
thrown from.

(Both the classes for exception objects, and for exception handlers,
would then be descendants from class Coroutine)

--
$a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca
);{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "$@[$a%6
]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}

Brent Dax

unread,
Jun 26, 2003, 8:08:26 PM6/26/03
to Benjamin Goldberg, perl6-i...@perl.org
Benjamin Goldberg:
# Concievably, we could then examine the exception, and maybe decide
that
# it was nonfatal, and resume execution from just after the place it was
# thrown from.

The problem with that is that some exceptions are unresumable. For
example, exceptions thrown in C code are difficult to resume from,
especially if they represent e.g. a segfault. Exceptions that represent
things like a file failing to open can be difficult to handle if they're
thrown from an inner routine--you'd need to know where to put the
replacement filehandle.

Perhaps there can be an Exception::Resumable that inherits from both
Exception and Continuation, but I don't think that normal exceptions can
or should be resumable.

--Brent Dax <bren...@cpan.org>
Perl and Parrot hacker

Gordon Henriksen

unread,
Jun 26, 2003, 8:38:33 PM6/26/03
to Benjamin Goldberg, perl6-i...@perl.org
The most fundamental feature throwing an exception is that it transfers
program execution from the call site. Allowing the caller to resume
execution at that site is a very dangerous form of action at a distance.

I think you'd be better off a giving the caller an explicit way to
inhibit throwing an exception. That is, use program design rather than
language features to provide this functionality. e.g., a delegate:

$ex = new My::Exception: ...;
die $ex
unless .delegate && .delegate.should_ignore_ex($_, $ex));

Not only is the above pattern clearer to read and less afflicted by
action at a distance, but it provides a wider bidirectional interface.

--

Gordon Henriksen
IT Manager
ICLUBcentral Inc.
gor...@iclub.com

Matt Fowles

unread,
Jun 27, 2003, 4:05:50 PM6/27/03
to perl6-i...@perl.org
Gordon Henriksen wrote:
> The most fundamental feature throwing an exception is that it transfers
> program execution from the call site. Allowing the caller to resume
> execution at that site is a very dangerous form of action at a distance.
>
> I think you'd be better off a giving the caller an explicit way to
> inhibit throwing an exception. That is, use program design rather than
> language features to provide this functionality. e.g., a delegate:

However, I think the Ruby sopports resumable exceptions, so we need to
be able to do it at some level.

Matt

Dan Sugalski

unread,
Jun 29, 2003, 1:23:17 PM6/29/03
to Brent Dax, Benjamin Goldberg, perl6-i...@perl.org
At 5:08 PM -0700 6/26/03, Brent Dax wrote:
>Benjamin Goldberg:
># Concievably, we could then examine the exception, and maybe decide
>that
># it was nonfatal, and resume execution from just after the place it was
># thrown from.
>
>The problem with that is that some exceptions are unresumable. For
>example, exceptions thrown in C code are difficult to resume from,
>especially if they represent e.g. a segfault. Exceptions that represent
>things like a file failing to open can be difficult to handle if they're
>thrown from an inner routine--you'd need to know where to put the
>replacement filehandle.

Exactly. Resumable exceptions should be under the control of the code
throwing the exception, in which case it can stick a resume
continuation object into the exception it throws.

Benjamin Goldberg

unread,
Jun 30, 2003, 11:53:07 AM6/30/03
to perl6-i...@perl.org
Brent Dax wrote:
>
> Benjamin Goldberg:
> # Concievably, we could then examine the exception, and maybe decide
> # that it was nonfatal, and resume execution from just after the place
> # it was thrown from.

>
> The problem with that is that some exceptions are unresumable. For
> example, exceptions thrown in C code are difficult to resume from,
> especially if they represent e.g. a segfault. Exceptions that
> represent things like a file failing to open can be difficult to
> handle if they're thrown from an inner routine--you'd need to know
> where to put the replacement filehandle.
>
> Perhaps there can be an Exception::Resumable that inherits from both
> Exception and Continuation, but I don't think that normal exceptions
> can or should be resumable.

I thought that warnings were to be implemented as exceptions... in which
case, our exception handler (warning handler) needs to choose whether to
resume execution at the place that the warning was produced, or to die,
or... something.

Should the "raise" opcode produce resumable exceptions?

Piers Cawley

unread,
Jun 30, 2003, 7:36:40 AM6/30/03
to l...@toetsch.at, Dan Sugalski, perl6-i...@perl.org
Leopold Toetsch <l...@toetsch.at> writes:

> Dan Sugalski <d...@sidhe.org> wrote:
>> Exception handlers really strike me as anonymous lexically scoped
>> subroutines that get called with just one parameter--the exception
>> object. As far as the engine should be concerned, when an exception
>> is taken we just take a continuation with the address being the start
>> of the code that handles the exception.
>
> Reading through pdd06 the following is not really speced (IMHO):
>
> Exception handlers are dynamically scoped, and any
> exception handler set in a scope will be removed when that
> scope is exited.
>
> How do we remove exception handlers on scope exit. Is this done, when we
> encounter a C<pop_pad> instruction? Or should the HL emit a C<clear_eh>
> opcode?
> As the exception handlers live on the control stack, there is not much
> connection between a lexical pad being popped off and removing
> exceptiion handlers in scope.

What does a lexical pad have to do with dynamic scoping? I thought
that the control stack was where dynamically scoped information
lived...

--
Piers

Dan Sugalski

unread,
Jun 30, 2003, 1:18:55 PM6/30/03
to perl6-i...@perl.org
At 11:53 AM -0400 6/30/03, Benjamin Goldberg wrote:
>Brent Dax wrote:
>>
>> Benjamin Goldberg:
>> # Concievably, we could then examine the exception, and maybe decide
>> # that it was nonfatal, and resume execution from just after the place
>> # it was thrown from.
>>
>> The problem with that is that some exceptions are unresumable. For
>> example, exceptions thrown in C code are difficult to resume from,
>> especially if they represent e.g. a segfault. Exceptions that
>> represent things like a file failing to open can be difficult to
>> handle if they're thrown from an inner routine--you'd need to know
>> where to put the replacement filehandle.
>>
>> Perhaps there can be an Exception::Resumable that inherits from both
>> Exception and Continuation, but I don't think that normal exceptions
>> can or should be resumable.
>
>I thought that warnings were to be implemented as exceptions...

Nope. Warnings are warnings, and exceptions are exceptions. Warnings
can be promoted to exceptions if need be, but they're separate things
and don't share a common base.

Leopold Toetsch

unread,
Jul 1, 2003, 7:48:53 AM7/1/03
to Benjamin Goldberg, perl6-i...@perl.org
Benjamin Goldberg <ben.go...@hotpop.com> wrote:

> Should the "raise" opcode produce resumable exceptions?

There is no problem with resuming after an opcode. E.g. when C<raise>
is:

invokecc Px # call exception handler

and the handler returns by C<invoke P1> i.e. via the return
continuation, execution just resumes.

But when an exception is thrown somewhere inside C code, I can't imagine
to resume there.

leo

0 new messages