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
> 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
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>
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...)
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
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
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;}
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
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
However, I think the Ruby sopports resumable exceptions, so we need to
be able to do it at some level.
Matt
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.
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?
> 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
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.
> 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