Patrick R. Michaud wrote:
PDD23:67 has:
: =item B<throw I<EXCEPTION>>
:
: Throw an exception consisting of the given I<EXCEPTION> PMC. Active exception
: handlers (if any) will be invoked with I<EXCEPTION> as the only parameter.
:
:
: =item B<throw I<EXCEPTION> [ , I<CONTINUATION> ]>
:
: Throw an exception consisting of the given I<EXCEPTION> PMC after taking
: a continuation at the next opcode. When a I<CONTINUATION> is passed in,
: it will use that instead. Active exception handlers (if any) will be
: invoked with I<EXCEPTION> and the given continuation as parameters.
This looks weird in a couple of respects. The second C<throw>
opcode shows I<CONTINUATION> as an optional parameter, which
would seem to be in conflict with the first form (i.e., they
end up being identical if I<CONTINUATION> is omitted).
Next, reading the above makes it look as though exception handlers
can sometimes be invoked with a single parameter (the exception)
and sometimes with two parameters (the exception and a continuation).
Perhaps it would be better to have a consistent calling interface?
(I do suppose we could say that the second parameter is always optional.)
I suspect much of the confusion comes from when C<throwcc> was
(apparently) eliminated in favor of a single C<throw> opcode,
but pdd23 wasn't made internally consistent.
Yes, C<throw> and C<throwcc> were collapsed into one opcode, and left
some editing junk behind.
I just changed it to one entry for C<throw>.
Also, note that the single-argument C<throw> opcode is currently
doing more than simply cause exception handlers to be invoked --
it's also takes a resume continuation and stores it in the
I<EXCEPTION> PMC itself (src/ops/core.ops:817). This would seem
to be in conflict with the next sentence at pdd23:80 :
: Any type of PMC can be thrown as an exception.
Clearly we cannot use the single-argument C<throw> on a PMC that
doesn't have a "resume" attribute for us to store the
resume continuation.
Personally I like the idea that "any PMC can be thrown as an
exception", which would seem to argue against forcing resume
continuations into the thrown PMC (which might not have a slot
for them). So, rather than saying that anything thrown as an
exception contains its resume continuation, perhaps we should
say that all handlers are invoked with the exception and resume
continuation as arguments, and the single-argument throw simply
takes a continuation at the next instruction to pass to the
handler(s).
Alternatively, we could say that C<throw> only places a resume
continuation into PMCs that "does exception", but somehow I
find this less desirable than the above approach.
Okay, PDD cleaned up. The code to directly support throwing any
arbitrary type would require significant circumlocution (read:
inefficient, difficult to maintain), so it's not desirable. It's not
just a matter of removing the return continuation from the exception
object, we'd have to remove all metadata from the exception object
(stacktrace, payload, handler iterator, type and severity information),
and either pass all that information as arguments throughout the system
(expensive and error-prone) or store it as global state information
(error-prone, and bad for a clean implementation of concurrency).
But, an individual HLL can store any arbitrary PMC value as the payload
of an exception object, and act as if it had thrown an arbitrary PMC as
an exception.
Allison