fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / docs / pdds / pdd23_exceptions.pod
blobc1ffcba9bbdb9daa9bc437ac633a27a340247430
1 # Copyright (C) 2001-2010, Parrot Foundation.
2 # $Id$
4 =head1 PDD 23: Exceptions
6 =head2 Abstract
8 This document defines the requirements and implementation strategy for
9 Parrot's exception system.
11 =head2 Version
13 $Revision$
15 =head2 Description
17 I<Exceptions> are indications by running code that something unusual -- an
18 "exception" to the normal processing -- has occurred.  When code detects an
19 exceptional condition, it I<throws> an exception object.  Before this occurs,
20 code can register exception I<handlers>, which are functions (or closures)
21 which may (but are not obligated to) I<handle> the exception.  Some exceptions
22 permit continued execution immediately after the I<throw>; some don't.
24 Exceptions transfer control to a piece of code outside the normal flow of
25 control.  They are mainly used for error reporting or cleanup tasks.
27 (A digression on terminology: In a system analysis sense, the word "exception"
28 usually refers to the exceptional event that requires out-of-band handling.
29 However, in Parrot, "exception" also refers to the object that holds all the
30 information describing the exceptional condition: the nature of the exception,
31 the error message describing it, and other ancillary information.  The
32 specific type (class) of an exception object indicates its category.)
34 =head3 Exception Opcodes
36 These are the opcodes relevant to exceptions and exception handlers:
38 =over
40 =item B<push_eh I<LABEL>>
42 =item B<push_eh I<EXCEPTIONHANDLER_PMC>>
44 Push an exception handler pmc onto the exception handler stack.
46 When an exception is thrown, Parrot walks up the stack of active exception
47 handlers, invoking each one in turn, but still in the dynamic context of the
48 exception (i.e. the call stack is I<not> unwound first).  See below for more
49 detail.
51 If a I<LABEL> is provided, Parrot creates and pushes an exception handler
52 that resumes execution at I<LABEL> if invoked, which has the effect of
53 unconditionally handling all errors, and unwinding the stack to that label.
55 If an I<EXCEPTIONHANDLER_PMC> is provided, Parrot pushes that pmc itself
56 onto the exception handler stack.
58 =item B<pop_eh>
60 Pop the most recently pushed exception handler off the exception handler
61 stack.
63 =item B<throw I<EXCEPTION> [ , I<CONTINUATION> ]>
65 Throw an exception consisting of the given I<EXCEPTION> PMC, after taking a
66 continuation at the next opcode. When a I<CONTINUATION> is passed in, it will
67 use that instead of generating a new continuation. Active exception handlers
68 (if any) will be invoked with I<EXCEPTION> as the only parameter. The
69 I<CONTINUATION> is stored in the 'resume' slot of the I<EXCEPTION>.
71 PMCs other than Parrot's Exception PMC may also be thrown, but they must
72 support the interface of an Exception PMC. An HLL may implement throwing any
73 arbitrary type of PMC, by storing that PMC in the 'payload' slot of the
74 Exception PMC.
76 Exception handlers can resume execution after handling the exception by
77 invoking the continuation stored in the 'resume' slot of the exception object.
78 That continuation must be invoked with no parameters; in other words, C<throw>
79 never returns a value.
81 =item B<rethrow I<EXCEPTION>>
83 While handling an exception, rethrow the exception to the next handler. Aside
84 from selecting a different handler, the behaviour of C<rethrow> is the same as
85 C<throw>. Each successive call to C<rethrow> will select a different handler,
86 until it exhausts the list of possible handlers. A rethrown exception that
87 is not handled behaves the same as an unhandled C<throw>n exception.
89 =item B<die [ I<MESSAGE> ]>
91 The C<die> opcode throws an exception of type C<exception;death> and severity
92 C<EXCEPT_error> with a payload of I<MESSAGE>.  The exception payload is a
93 C<String> PMC containing I<MESSAGE>.
95 {{NOTE: Exception classes NYI.  Currently throws CONTROL_ERROR}}
97 The default when no I<MESSAGE> is given is "Fatal exception at LINE in
98 FILE." followed by a backtrace.
100 {{NOTE: Not yet implemented.}}
102 If this exception is not handled, it results in Parrot returning an error
103 indication and the stringification of I<MESSAGE> to its embedding environment.
104 When running standalone, this means writing the stringification of I<MESSAGE>
105 to standard error and executing the standard Parrot function C<Parrot_exit>,
106 to shut down the interpreter cleanly.
108 =item B<exit [ I<EXITCODE> ]>
110 Throw an exception of type C<exception;exit> with a payload of I<EXITCODE>,
111 which defaults to zero, as an Integer PMC.
113 {{NOTE: Exception classes NYI. Currently throws a type based on the
114 EXITCODE.}}
116 If not handled, this exception results in Parrot returning I<EXITCODE>
117 as a status to its embedded environment, or when running standalone,
118 to execute the C function C<exit(I<EXITCODE>)>.
120 {{NOTE: This is not currently the case.  Parrot now stores the EXITCODE
121 argument in the type, not the payload}}
123 =back
125 =head3 Exception Introspection Opcodes
127 These are the opcodes relevant to introspection of the exception handler
128 stack:
130 =over
132 =item B<count_eh>
134 Return the quantity of currently active exception handlers.
136 =back
139 =head3 Order of Operations in Exception Handling
141 When B<throw> is called, for all active exception handlers, in LIFO order:
143 =over
145 =item 1
146 Find the topmost exception handler.
148 =item 2
149 Push an exception record somewhere, presumably on the exception handler
150 stack. The exception record contains a pointer to an exception handler
151 block, an exception PMC, and (optionally) a continuation.
153 =item 3
154 Invoke the handler (note: this is still in the thrower's dynamic
155 context).
157 =item 4
158 If the exception is C<rethrow>n, repeat steps 1-3 above, finding the next
159 exception handler.
161 =item 5
162 If no handler is found, and the exception is non-fatal (such as a
163 warning), and there is a continuation in the exception record (because
164 the throwing opcode was C<throw>), invoke the continuation (resume
165 execution). Whether to resume or die when an exception isn't handled is
166 determined by the severity of the exception.
168 =item 6
169 Otherwise terminate the program like C<die>.
171 =back
173 When running an embedded Parrot interpreter, the interpreter does not
174 immediately terminate on an unhandled exception, it merely returns
175 control to the embedding program and stores the unhandled exception so
176 that it may be queried by the embedding program. The embedding program
177 may choose to handle the exception and continue execution by invoking
178 the exception's continuation.
180 =head2 Implementation
182 =head3 Exception Object Interface
184 All of Parrot's standard exceptions provide at least the following interface.
185 It is recommended that all classes intended for throwing also provide at least
186 this interface as well.
188 =over 4
190 =item B<PMC *get_attr_str(STRING *name)>
192 Retrieve an attribute from the Exception. All exceptions will have at least
193 C<message>, C<severity>, C<resume>, and C<payload> attributes.
195 The C<message> is an exception's human-readable self-description.  Note that
196 the type of the returned PMC isn't required to be C<String>, but you should
197 still be able to stringify and print it.
199 The C<severity> is an integer from an internal Parrot enum of exception
200 severities.
202 The C<resume> is a continuation that you can invoke to resume normal execution
203 of the program.
205 The C<payload> more specifically identifies the detailed cause/nature of
206 the exception.  Each exception class will have its own specific payload
207 type(s).  See the table of standard exception classes for examples.
209 =item B<PMC *set_attr_str(STRING *name, PMC *value)>
211 Set an attribute on the Exception. All exceptions will have at least
212 C<message>, C<severity>, C<resume>, and C<payload> attributes.
214 =item B<PMC *annotations()>
216 Gets a Hash containing any bytecode annotations in effect at the point where
217 the exception was thrown. If none were in effect, returns an empty Hash. See
218 the PIR PDD for syntax for declaring and semantics of bytecode annotations.
220 =item B<PMC *annotations(STRING *name)>
222 Returns a PMC representing the bytecode annotation with the key specified in
223 C<name> at the point where the exception was thrown. If there was no such
224 annotation in effect, a NULL PMC will be returned.
226 =item B<PMC *backtrace()>
228 Gets a representation of the backtrace at the point that this exception was
229 thrown. Returns an array of hashes. Each array element represents a caller in
230 the backtrace, the most recent caller first. The hash has two keys: C<sub>,
231 which holds the PMC representing the sub, and C<annotations> which is a hash
232 of the annotations at the point where the exception was thrown for the current
233 sub, or for the point of the call a level deeper for the rest.
235 =back
237 =head3 Standard Parrot Exceptions
239 Parrot comes with a small hierarchy of classes designed for use as exceptions.
240 Parrot throws them when internal Parrot errors occur, but any user code can
241 throw them too.
243 {{NOTE: Currently NYI.  Parrot currently uses integers to represent exception
244 types.}}
246 {{NOTE: Questions about how this interoperates with custom HLL exception
247 classes}}
249 =over
251 =item B<exception>
253 Base class of all standard exceptions.  Provides no special functionality.
254 Exists for the purpose of C<isa> testing.
256 =item B<exception;death>
258 Exception type that is thrown by the C<die> opcode. See the description of
259 the C<die> opcode in this document.
261 =item B<exception;errno>
263 A system error as reported in the C variable C<errno>.  Payload is an integer.
264 Message is the return value of the standard C function C<strerror()>.
266 =item B<exception;exit>
268 Exception type that is thrown by the C<exit> opcode. See the description of
269 the C<exit> opcode in this document.
271 =item B<exception;math>
273 Generic base class for math errors.
275 =item B<exception;math;division_by_zero>
277 Division by zero (integer or float).  No payload.
279 =item B<exception;domain>
281 Generic base class for miscellaneous domain (input value) errors.  Payload is
282 an array, the first element of which is the operation that failed (e.g. the
283 opcode name); subsequent elements depend on the value of the first element.
285 (Note: There is not a separate exception class for every operation that might
286 throw a domain exception.  Class proliferation is expensive, both to Parrot
287 and to the humans working with it who have to memorize a class hierarchy.  But
288 I understand the temptation.)
290 =item B<exception;lexical>
292 An C<find_lex> or C<store_lex> operation failed because a given lexical
293 variable was not found.  Payload is an array: [0] the name of the lexical
294 variable that was not found, [1] the LexPad in which it was not found.
296 =back
298 =head3 Opcodes that Throw Exceptions
300 Exceptions have been incorporated into built-in opcodes in a limited way.  For
301 the most part, they're used when the return value is either impractical to
302 check (perhaps because we don't want to add that many error checks in line),
303 or where the output type is unable to represent an error state (e.g. the
304 output I register of the C<ord> opcode).
306 The C<div>, C<fdiv>, and C<cmod> opcodes throw
307 C<exception;math;division_by_zero>.
309 The C<ord> opcode throws C<exception;domain> when it's passed an empty
310 argument or a string index that's outside the length of the string.  Payload
311 is an array, first element being the string 'ord'.
313 The C<find_encoding> opcode throws C<exception;domain> if the encoding name
314 it's looking up doesn't exist.  Payload is an array: [0] string
315 'find_encoding', [1] encoding name that was not found.
317 The C<trans_encoding> opcode throws C<exception;domain> on "information loss"
318 (presumably, this means when one encoding doesn't have a one-to-one
319 correspondence in the other encoding).  Payload is an array: [0] string
320 'trans_encoding', [1] source encoding name, [2] destination encoding name, [3]
321 untranslatable code point.
323 Parrot's default version of the C<LexPad> PMC throws C<exception;lexical> for
324 some error conditions, though other implementations can choose to return error
325 values instead.
327 By default, the C<find_lex> and C<store_lex> opcodes throw an exception
328 (C<exception;lexical>) when the given name can't be found in any visible
329 lexical pads.  However, this behavior is only a default, as provided by the
330 default Parrot lexical pad PMC C<LexPad>.  If a given HLL has its own lexical
331 pad PMC, its behavior may be very different.  (For example, in Tcl,
332 C<store_lex> is likely to succeed every time, as creating new lexicals at
333 runtime is OK in Tcl.)
335 {{ TODO: List any other opcodes that currently throw exceptions and
336 general categories of opcodes that should throw exceptions. }}
338 Other opcodes respond to an C<errorson> setting to decide whether to
339 throw an exception or return an error value. C<get_hll_global> and
340 C<get_root_global> throw an
341 exception (or returns a Null PMC) if the global name requested doesn't
342 exist. C<find_name> throws an exception (or returns a Null PMC) if the
343 name requested doesn't exist in a lexical, current, global, or built-in
344 namespace.
346 {{ TODO: "errorson" as specified is dynamically rather than lexically
347 scoped; is this good? Probably not good. Let's revisit it when we get
348 the basic exceptions functionality implemented. }}
350 It's a little odd that so few opcodes throw exceptions (these are the
351 ones that are documented, but a few others throw exceptions internally
352 even though they aren't documented as doing so). It's worth considering
353 either expanding the use of exceptions consistently throughout the
354 opcode set, or eliminating exceptions from the opcode set entirely. The
355 strategy for error handling should be consistent, whatever it is. [I
356 like the way C<LexPad>s and the C<errorson> settings provide the option
357 for exception-based or non-exception-based implementations, rather than
358 forcing one or the other.]
360 {{ NOTE: There are a couple of different factors here.  One is the
361 ability to globally define the severity of certain exceptions or
362 categories of exceptions without needing to define a handler for each
363 one. (e.g. Perl 6 may have pragmas to set how severe type-checking
364 errors are. A simple "incompatible type" error may be fatal under one
365 pragma, a resumable warning under another pragma, and completely silent
366 under a third pragma.) Another is the ability to "defang" opcodes so
367 they return error codes instead of throwing exceptions. We might provide
368 a very simple interface to catch an exception and capture its payload
369 without the full complexity of manually defining exception handlers
370 (though it would still be implemented as an exception handler
371 internally). Something like:
373 =begin PIR_FRAGMENT_TODO
375   .local pmc error_code
376   .capture_start error_code
377   $P1 = find_lex 'foo'
378   .capture_end
380   # error_code contains what would have been the "error" return value
382 =end PIR_FRAGMENT_TODO
384 This could eliminate the need for "defanging" because it would be almost
385 as easy to use as error codes. It could be implemented once for all
386 exceptional opcodes, instead of needing to be defined for each one. And,
387 it still keeps the error information out-of-band, instead of mixing the
388 error in with normal return values. }}
390 =head3 Exception Object Interface
392 =head4 Retrieving the Exception Message
394 The exception message is stored in the 'message' attribute:
396 =begin PIR_FRAGMENT
398   # ...
399  handler:
400   .local pmc exception
401   .local string message
402   .get_results (exception)
403   message = exception['message']
404   say message
406 =end PIR_FRAGMENT
409 =head4 Resuming after Exceptions
411 Exceptions thrown by standard Parrot opcodes (like the one thrown by
412 C<get_hll_global> above or by the C<throw> opcode) are always resumable,
413 so when the exception handler function returns normally it continues
414 execution at the opcode immediately after the one that threw the
415 exception. Other exceptions at the run-loop level are also generally
416 resumable.
418 {{NOTE: Currently only implemented for the actual throwing opcodes, throw,
419 die, exit.}}
421 You resume from an exception by invoking the return continuation stored
422 in the 'resume' attribute of the exception.
424 =begin PIR_FRAGMENT
426   push_eh handler
427   $P0 = new 'Exception'          # create new exception object
428   throw $P0                      # throw it
429   pop_eh
430   say "Everything is just fine."
431   .return()
432  handler:
433   .local pmc exception, continuation
434   .get_results (exception)
435   continuation = exception['resume']
436   continuation()
438 =end PIR_FRAGMENT
440 =head2 References
442 F<src/ops/core.ops>, F<src/exceptions.c>, F<src/pmc/exception.pmc>,
443 F<src/pmc/exceptionhandler.pmc>
445 =cut
447 __END__
448 Local Variables:
449   fill-column:78
450 End: