[perl6]:
[parrot.git] / docs / pdds / pdd23_exceptions.pod
blob14d59beec1149752b033f391371a7c155ef13857
1 # Copyright (C) 2001-2007, The Perl Foundation.
2 # $Id$
4 {{ NOTE: "rethrow", and "pushaction" are removed, and "die" is different }}
5 {{ TODO: enable backtrace }}
7 =head1 NAME
9 docs/pdds/pdd23_exceptions.pod - Parrot Exceptions
11 =head1 ABSTRACT
13 This document defines the requirements and implementation strategy for
14 Parrot's exception system.
16 =head1 VERSION
18 $Revision$
20 =head1 DESCRIPTION
22 I<Exceptions> are indications by running code that something unusual -- an
23 "exception" to the normal processing -- has occurred.  When code detects an
24 exceptional condition, it I<throws> an exception object.  Before this occurs,
25 code can register exception I<handlers>, which are functions (or closures)
26 which may (but are not obligated to) I<handle> the exception.  Some exceptions
27 permit continued execution immediately after the I<throw>; some don't.
29 Exceptions transfer control to a piece of code outside the normal flow of
30 control.  They are mainly used for error reporting or cleanup tasks.
32 (A digression on terminology: In a system analysis sense, the word "exception"
33 usually refers to the exceptional event that requires out-of-band handling.
34 However, in Parrot, "exception" also refers to the object that holds all the
35 information describing the exceptional condition: the nature of the exception,
36 the error message describing it, and other ancillary information.  The
37 specific type (class) of an exception object indicates its category.)
39 =head2 Exception Opcodes
41 These are the opcodes relevant to exceptions and exception handlers:
43 =over
45 =item B<push_eh I<LABEL>>
47 =item B<push_eh I<INVOCABLE_PMC>>
49 Push an invocable PMC -- usually a closure or, in rarer cases, a subroutine or
50 continuation -- onto the exception handler stack.
52 When an exception is thrown, Parrot walks up the stack of active exception
53 handlers, invoking each one in turn, but still in the dynamic context of the
54 exception (i.e. the call stack is I<not> unwound first).  See below for more
55 detail.
57 If a I<LABEL> is provided, Parrot creates and pushes a continuation that
58 resumes execution at I<LABEL> if invoked, which has the effect of
59 unconditionally handling all errors, and unwinding the stack to that label.
61 If a I<INVOCABLE_PMC> is provided, Parrot pushes the pmc which will execute
62 if invoked, which has the effect of unconditionally handling all errors,
63 replacing the stack with that execution context of the invocable pmc.
65 =item B<pop_eh>
67 Pop the most recently pushed exception handler off the exception handler stack.
69 =item B<throw I<EXCEPTION>>
71 Throw an exception consisting of the given I<EXCEPTION> PMC.  Active exception
72 handlers (if any) will be invoked with I<EXCEPTION> as the only parameter.
74 Throwing an exception with C<throw> is a one-way trip (unless you have made
75 other arrangements) because Parrot does not take a continuation after this
76 opcode.  (But see B<throwcc> below.)
78 Any type of PMC can be thrown as an exception.  However, if there's any chance
79 of cross-language calls -- and in a Parrot environment, cross-language
80 operations are kind of the point -- then you should be prepared to catch
81 exception classes you would never have thrown yourself.
83 That said, it is I<VERY STRONGLY RECOMMENDED> that any thrown PMC that can
84 possibly escape your private sandbox should meet the minimal interface
85 requirements of the C<parrot;exception> class, described below.
87 =item B<throwcc I<EXCEPTION> [ , I<CONTINUATION> ]>
89 Throw an exception consisting of the given I<EXCEPTION> PMC after taking
90 a continuation at the next opcode.  When a I<CONTINUATION> is passed in,
91 it will use that instead. Active exception handlers (if any) will be
92 invoked with I<EXCEPTION> and the given continuation as parameters.
94 Except for the continuation which is passed to exception handlers,
95 C<throwcc> is just like C<throw>.  This opcode is useful for exceptions
96 that are more like warnings or notices than errors.
98 Exception handlers can resume execution immediately after the C<throwcc>
99 opcode by executing the C<handled> opcode, and then invoking the given
100 continuation which they receive as a parameter.  That continuation must be
101 invoked with no parameters; in other words, C<throwcc> never returns a
102 value.
104 =item B<die [ I<MESSAGE> ]>
106 The C<die> opcode throws an exception of type C<exception;death> with a
107 payload of I<MESSAGE>.  If I<MESSAGE> is a string register, the exception
108 payload is a C<String> PMC containing I<MESSAGE>; if I<MESSAGE> is a PMC, it
109 is used directly as the exception payload.
111 The default when no I<MESSAGE> is given is "Fatal exception at LINE in
112 FILE." followed by a backtrace.
114 If this exception is not handled, it results in Parrot returning an error
115 indication and the stringification of I<MESSAGE> to its embedding environment.
116 When running standalone, this means writing the stringification of I<MESSAGE>
117 to standard error and executing the standard C function C<exit(EXIT_FAILURE)>.
119 =item B<exit [ I<EXITCODE> ]>
121 Throw an exception of type C<exception;exit> with a payload of I<EXITCODE>,
122 which defaults to zero, as an Integer PMC.
124 If not handled, this exception results in Parrot returning I<EXITCODE>
125 as a status to its embedded environment, or when running standalone,
126 to execute the C function C<exit(I<EXITCODE>)>.
128 =item B<handled I<EXCEPTION>>
130 While handling an exception, tell Parrot that the exception has been handled
131 and should be removed from the stack of active exceptions.  This opcode is an
132 exception handler's way of telling Parrot that it has handled the exception.
134 =back
136 =head2 Exception Introspection Opcodes
138 These are the opcodes relevant to introspection of the exception handler stack:
140 =over
142 =item B<count_eh>
144 Return the quantity of currently active exception handlers.
146 =item B<get_eh I<index>>
148 Return the exception handler at I<index>. The index is an offset from the top
149 of the stack, with '0' being the top.
151 =item B<get_all_eh>
153 Return a resizable pmc array of all current exception handlers.
155 =back
158 =head2 Order of Operations in Exception Handling
160 When B<throw> or B<throwcc> is called, for all active exception
161 handlers, in LIFO order:
163 =over
165 =item 1
166 Find the topmost exception handler.
168 =item 2
169 Push an exception record somewhere, presumably on the exception handler
170 stack.  The exception record contains a pointer to an exception handler
171 block, an exception PMC, and (optionally) a continuation.
173 =item 3
174 Invoke the handler (note: this is still in the thrower's dynamic
175 context).
177 =back
179 If the handler returns without calling C<handled>:
181 =over
183 =item 1
184 Find the "exception handling in progress" record.
186 =item 2
187 Find the next exception handler.
189 =item 3
190 If the handler is found, invoke it.
193 =item 4
194 If no handler is found, and the exception is non-fatal (such as a
195 warning), and there is a continuation in the exception record (because
196 the throwing opcode was C<throwcc>), invoke the continuation (resume
197 execution). Whether to resume or die when an exception isn't handled is
198 determined by the severity of the exception.
200 =item 5
201 Otherwise terminate program a la C<die>. 
203 =back
205 When running an embedded Parrot interpreter, the interpreter does not
206 immediately terminate on an unhandled exception, it merely returns
207 control to the embedding program and stores the unhandled exception so
208 that it may be queried by the embedding program. The embedding program
209 may choose to handle the exception and continue execution by invoking
210 the exception's continuation.
213 When the C<handled> opcode is called:
215 =over
217 =item 1
218 Pop and destroy the exception record.
220 =item 2
221 If there was a continuation in the exception record, invoke the
222 continuation.
224 =back
227 =head1 IMPLEMENTATION
229 =head2 Exception Object Interface
231 All of Parrot's standard exceptions provide at least the following interface.
232 It is recommended that all classes intended for throwing also provide at least
233 this interface as well.
235 =over 4
237 =item B<PMC *get_attr_str(STRING *name)>
239 Retreive an attribute from the Exception. All exceptions will have at least
240 C<message>, C<severity>, and C<payload> attributes.
242 The C<message> is an exception's human-readable self-description.  Note that
243 the type of the returned PMC isn't required to be C<String>, but you should
244 still be able to stringify and print it.
246 The C<payload> more specifically identifies the detailed cause/nature of
247 the exception.  Each exception class will have its own specific payload
248 type(s).  See the table of standard exception classes for examples.
250 =item B<PMC *set_attr_str(STRING *name, PMC *value)>
252 Set an attribute on the Exception. All exceptions will have at least
253 C<message>, C<severity>, and C<payload> attributes.
255 =back
257 =head2 Standard Parrot Exceptions
259 Parrot comes with a small hierarchy of classes designed for use as exceptions.
260 Parrot throws them when internal Parrot errors occur, but any user code can
261 throw them too.
263 =over
265 =item B<exception>
267 Base class of all standard exceptions.  Provides no special functionality.
268 Exists for the purpose of C<isa> testing.
270 =item B<exception;errno>
272 A system error as reported in the C variable C<errno>.  Payload is an integer.
273 Message is the return value of the standard C function C<strerror()>.
275 =item B<exception;math>
277 Generic base class for math errors.
279 =item B<exception;math;division_by_zero>
281 Division by zero (integer or float).  No payload.
283 =item B<exception;domain>
285 Generic base class for miscellaneous domain (input value) errors.  Payload is
286 an array, the first element of which is the operation that failed (e.g. the
287 opcode name); subsequent elements depend on the value of the first element.
289 (Note: There is not a separate exception class for every operation that might
290 throw a domain exception.  Class proliferation is expensive, both to Parrot
291 and to the humans working with it who have to memorize a class hierarchy.  But
292 I understand the temptation.)
294 =item B<exception;lexical>
296 An C<find_lex> or C<store_lex> operation failed because a given lexical
297 variable was not found.  Payload is an array: [0] the name of the lexical
298 variable that was not found, [1] the LexPad in which it was not found.
300 =back
302 =head2 Opcodes that Throw Exceptions
304 Exceptions have been incorporated into built-in opcodes in a limited way.  For
305 the most part, they're used when the return value is either impractical to
306 check (perhaps because we don't want to add that many error checks in line),
307 or where the output type is unable to represent an error state (e.g. the
308 output I register of the C<ord> opcode).
310 The C<div>, C<fdiv>, and C<cmod> opcodes throw
311 C<exception;math;division_by_zero>.
313 The C<ord> opcode throws C<exception;domain> when it's passed an empty
314 argument or a string index that's outside the length of the string.  Payload
315 is an array, first element being the string 'ord'.
317 The C<classoffset> opcode throws C<exception;domain> when it's asked to
318 retrieve the attribute offset for a class that isn't in the object's
319 inheritance hierarchy.  Payload is an array: [0] string 'classoffset',
320 [1] object in question, [2] ID of class not found.
322 The C<find_charset> opcode throws C<exception;domain> if the charset name it's
323 looking up doesn't exist.  Payload is an array: [0] string 'find_charset', [1]
324 charset name that was not found.
326 The C<trans_charset> opcode throws C<exception;domain> on "information loss"
327 (presumably, this means when one charset doesn't have a one-to-one
328 correspondence in the other charset).  Payload is an array: [0] string
329 'trans_charset', [1] source charset name, [2] destination charset name, [3]
330 untranslatable code point.
332 The C<find_encoding> opcode throws C<exception;domain> if the encoding name
333 it's looking up doesn't exist.  Payload is an array: [0] string
334 'find_encoding', [1] encoding name that was not found.
336 The C<trans_encoding> opcode throws C<exception;domain> on "information loss"
337 (presumably, this means when one encoding doesn't have a one-to-one
338 correspondence in the other encoding).  Payload is an array: [0] string
339 'trans_encoding', [1] source encoding name, [2] destination encoding name, [3]
340 untranslatable code point.
342 Parrot's default version of the C<LexPad> PMC throws C<exception;lexical> for
343 some error conditions, though other implementations can choose to return error
344 values instead.
346 By default, the C<find_lex> and C<store_lex> opcodes throw an exception
347 (C<exception;lexical>) when the given name can't be found in any visible
348 lexical pads.  However, this behavior is only a default, as provided by the
349 default Parrot lexical pad PMC C<LexPad>.  If a given HLL has its own lexical
350 pad PMC, its behavior may be very different.  (For example, in Tcl,
351 C<store_lex> is likely to succeed every time, as creating new lexicals at
352 runtime is OK in Tcl.)
354 {{ TODO: List any other opcodes that currently throw exceptions and
355 general categories of opcodes that should throw exceptions. }}
357 Other opcodes respond to an C<errorson> setting to decide whether to
358 throw an exception or return an error value. C<find_global> throws an
359 exception (or returns a Null PMC) if the global name requested doesn't
360 exist. C<find_name> throws an exception (or returns a Null PMC) if the
361 name requested doesn't exist in a lexical, current, global, or built-in
362 namespace.
364 {{ TODO: "errorson" as specified is dynamically rather than lexically
365 scoped; is this good? Probably not good. Let's revisit it when we get
366 the basic exceptions functionality implemented. }}
368 It's a little odd that so few opcodes throw exceptions (these are the
369 ones that are documented, but a few others throw exceptions internally
370 even though they aren't documented as doing so). It's worth considering
371 either expanding the use of exceptions consistently throughout the
372 opcode set, or eliminating exceptions from the opcode set entirely. The
373 strategy for error handling should be consistent, whatever it is. [I
374 like the way C<LexPad>s and the C<errorson> settings provide the option
375 for exception-based or non-exception-based implementations, rather than
376 forcing one or the other.]
378 {{ NOTE: There are a couple of different factors here.  One is the
379 ability to globally define the severity of certain exceptions or
380 categories of exceptions without needing to define a handler for each
381 one. (e.g. Perl 6 may have pragmas to set how severe type-checking
382 errors are. A simple "incompatible type" error may be fatal under one
383 pragma, a resumable warning under another pragma, and completely silent
384 under a third pragma.) Another is the ability to "defang" opcodes so
385 they return error codes instead of throwing exceptions. We might provide
386 a very simple interface to catch an exception and capture its payload
387 without the full complexity of manually defining exception handlers
388 (though it would still be implemented as an exception handler
389 internally). Something like:
391   .local pmc error_code
392   .capture_start error_code
393   $P1 = find_lex 'foo'
394   .capture_end
396   # error_code contains what would have been the "error" return value
398 This could eliminate the need for "defanging" because it would be almost
399 as easy to use as error codes. It could be implemented once for all
400 exceptional opcodes, instead of needing to be defined for each one. And,
401 it still keeps the error information out-of-band, instead of mixing the
402 error in with normal return values. }}
404 =head2 Resuming after Exceptions
406 Exceptions thrown by standard Parrot opcodes (like the one thrown by
407 C<find_global> above or by the C<throw> opcode) are always resumable,
408 so when the exception handler function returns normally it continues
409 execution at the opcode immediately after the one that threw the
410 exception. Other exceptions at the run-loop level are also generally
411 resumable.
413   $P0 = new 'String'
414   $P0 = "something bad happened"
415   $P1 = new ['parrot';'exception'], $P0  # create new exception object
416   throw $P1                              # throw it
418 {{ The above example doesn't work in r23568 -- see RT#48320. }}
420 =head1 ATTACHMENTS
422 None.
424 =head1 FOOTNOTES
426 None.
428 =head1 REFERENCES
430   src/ops/core.ops
431   src/exceptions.c
433 =cut
435 __END__
436 Local Variables:
437   fill-column:78
438 End: