2 Copyright (C) 2001-2008, Parrot Foundation.
7 src/pmc/exceptionhandler.pmc - Exception Handler PMC
11 When an exception handler is called, the exception object is passed as
12 C<REG_PMC(interp, 5)>, the original contents of this register is in the
13 exception object's C<_P5> attribute.
23 #include "parrot/oplib/ops.h"
25 /* HEADERIZER HFILE: none */
26 /* HEADERIZER BEGIN: static */
27 /* HEADERIZER END: static */
29 pmclass ExceptionHandler extends Continuation provides invokable auto_attrs {
31 ATTR PMC *handled_types;
32 ATTR PMC *handled_types_except;
33 ATTR INTVAL min_severity;
34 ATTR INTVAL max_severity;
40 Initializes the exception handler.
47 Parrot_ExceptionHandler_attributes * const attrs = PARROT_EXCEPTIONHANDLER(SELF);
50 attrs->min_severity = 0;
51 attrs->max_severity = 0;
52 attrs->handled_types = PMCNULL;
53 attrs->handled_types_except = PMCNULL;
55 /* an exception handler has no separate context; it's only a snapshot
56 * of an "earlier" context, which is contained in the interpreter's
57 * context - the stacks can only be deeper in the interpreter - so no
58 * mark of context is needed */
59 PObj_custom_mark_SET(SELF);
66 Mark any active exception handler data as live.
73 Parrot_ExceptionHandler_attributes * const attrs =
74 PARROT_EXCEPTIONHANDLER(SELF);
75 Parrot_gc_mark_PMC_alive(INTERP, attrs->handled_types);
76 Parrot_gc_mark_PMC_alive(INTERP, attrs->handled_types_except);
81 PMC * const result = SUPER();
82 /* This looks wrong, why wouldn't we want to mark the clone? */
83 PObj_custom_mark_CLEAR(result);
89 =item C<void set_integer_native(INTVAL)>
91 Mark whether the handler has been invoked.
97 VTABLE void set_integer_native(INTVAL value) {
98 PARROT_CONTINUATION(SELF)->invoked = value;
103 =item C<INTVAL get_integer()>
105 Check whether the handler has been invoked.
111 VTABLE INTVAL get_integer() {
112 return PARROT_CONTINUATION(SELF)->invoked;
117 =item C<opcode_t *invoke(void *next)>
119 Set up the environment for the exception handler to be invoked.
125 VTABLE opcode_t *invoke(void *next) {
126 opcode_t * const pc = PARROT_CONTINUATION(SELF)->address;
128 Parrot_continuation_check(INTERP, SELF);
129 Parrot_continuation_rewind_environment(INTERP, SELF);
131 /* switch code segment if needed */
132 if (INTERP->code != PARROT_CONTINUATION(SELF)->seg)
133 Parrot_switch_to_cs(INTERP, PARROT_CONTINUATION(SELF)->seg, 1);
153 =item C<METHOD can_handle(PMC *exception)>
155 Report whether the exception handler can handle a particular type of exception.
161 METHOD can_handle(PMC *exception) {
162 STRING * const sev = CONST_STRING(INTERP, "severity");
163 STRING * const ex_str = CONST_STRING(INTERP, "Exception");
165 INTVAL severity = VTABLE_get_integer_keyed_str(INTERP, exception, sev);
167 if (exception->vtable->base_type == enum_class_Exception
168 || VTABLE_isa(INTERP, exception, ex_str)) {
170 PMC *handled_types_except;
171 INTVAL min_severity, max_severity;
172 GET_ATTR_handled_types(INTERP, SELF, handled_types);
173 GET_ATTR_handled_types_except(INTERP, SELF, handled_types_except);
174 GET_ATTR_max_severity(INTERP, SELF, max_severity);
175 GET_ATTR_min_severity(INTERP, SELF, min_severity);
177 if (severity < min_severity) {
180 if (max_severity > 0 && severity > max_severity) {
183 if (! PMC_IS_NULL(handled_types)) {
184 const INTVAL elems = VTABLE_elements(INTERP, handled_types);
185 const INTVAL type = VTABLE_get_integer_keyed_str(INTERP, exception, CONST_STRING(INTERP, "type"));
188 for (i = 0; i < elems; ++i) {
189 INTVAL handled_type = VTABLE_get_integer_keyed_int(INTERP,
191 if (handled_type == type)
197 if (handled_types_except != PMCNULL) {
198 const INTVAL elems = VTABLE_elements(INTERP, handled_types_except);
199 const INTVAL type = VTABLE_get_integer_keyed_str(INTERP, exception, CONST_STRING(INTERP, "type"));
202 for (i = 0; i < elems; ++i) {
203 const INTVAL handled_type = VTABLE_get_integer_keyed_int(INTERP,
204 handled_types_except, i);
205 if (handled_type == type)
211 else if (max_severity > 0 || min_severity > 0) {
223 =item C<METHOD min_severity(INTVAL severity :optional, INTVAL have_severity :opt_flag)>
225 Set or get the minimum severity of the exception handler.
231 METHOD min_severity(INTVAL severity :optional, INTVAL have_severity :opt_flag) {
232 Parrot_ExceptionHandler_attributes * const attrs =
233 PARROT_EXCEPTIONHANDLER(SELF);
236 attrs->min_severity = severity;
238 severity = attrs->min_severity;
240 RETURN(INTVAL severity);
245 =item C<METHOD max_severity(INTVAL severity :optional, INTVAL have_severity :opt_flag)>
247 Set or get the maximum severity of the exception handler.
253 METHOD max_severity(INTVAL severity :optional, INTVAL have_severity :opt_flag) {
254 Parrot_ExceptionHandler_attributes * const attrs =
255 PARROT_EXCEPTIONHANDLER(SELF);
258 attrs->max_severity = severity;
260 severity = attrs->max_severity;
262 RETURN(INTVAL severity);
267 =item C<METHOD handle_types(PMC *types :slurpy)>
269 Set the exception types that the ExceptionHandler will handle.
275 METHOD handle_types(PMC *types :slurpy) {
276 Parrot_ExceptionHandler_attributes * const attrs =
277 PARROT_EXCEPTIONHANDLER(SELF);
278 attrs->handled_types =
279 VTABLE_elements(INTERP, types) > 0
286 =item C<METHOD handle_types_except(PMC *types :slurpy)>
288 Set the exception types that the ExceptionHandler will not handle.
294 METHOD handle_types_except(PMC *types :slurpy) {
295 Parrot_ExceptionHandler_attributes * const attrs =
296 PARROT_EXCEPTIONHANDLER(SELF);
297 attrs->handled_types_except =
298 VTABLE_elements(INTERP, types) > 0
315 * c-file-style: "parrot"
317 * vim: expandtab shiftwidth=4: