fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / src / pmc / exceptionhandler.pmc
blob100340487bb1706f80169d8c098efc178589e2df
1 /*
2 Copyright (C) 2001-2008, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/exceptionhandler.pmc - Exception Handler PMC
9 =head1 DESCRIPTION
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.
15 =head2 Methods
17 =over 4
19 =cut
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;
38 =item C<void init()>
40 Initializes the exception handler.
42 =cut
46     VTABLE void init() {
47         Parrot_ExceptionHandler_attributes * const attrs = PARROT_EXCEPTIONHANDLER(SELF);
48         SUPER();
49         attrs->invoked              = 0;
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);
60     }
64 =item C<void mark()>
66 Mark any active exception handler data as live.
68 =cut
72     VTABLE void mark() {
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);
77         SUPER();
78     }
80     VTABLE PMC *clone() {
81         PMC * const result = SUPER();
82         /* This looks wrong, why wouldn't we want to mark the clone? */
83         PObj_custom_mark_CLEAR(result);
84         return result;
85     }
89 =item C<void set_integer_native(INTVAL)>
91 Mark whether the handler has been invoked.
93 =cut
97     VTABLE void set_integer_native(INTVAL value) {
98         PARROT_CONTINUATION(SELF)->invoked = value;
99     }
103 =item C<INTVAL get_integer()>
105 Check whether the handler has been invoked.
107 =cut
111     VTABLE INTVAL get_integer() {
112         return PARROT_CONTINUATION(SELF)->invoked;
113     }
117 =item C<opcode_t *invoke(void *next)>
119 Set up the environment for the exception handler to be invoked.
121 =cut
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);
135         return pc;
136     }
141 =back
143 =head2 Methods
145 =over 4
147 =cut
153 =item C<METHOD can_handle(PMC *exception)>
155 Report whether the exception handler can handle a particular type of exception.
157 =cut
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)) {
169             PMC *handled_types;
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) {
178                 RETURN(INTVAL 0);
179             }
180             if (max_severity > 0 &&  severity > max_severity) {
181                 RETURN(INTVAL 0);
182             }
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"));
186                 INTVAL i;
188                 for (i = 0; i < elems; ++i) {
189                     INTVAL handled_type = VTABLE_get_integer_keyed_int(INTERP,
190                             handled_types, i);
191                     if (handled_type == type)
192                         RETURN(INTVAL 1);
193                 }
195                 RETURN(INTVAL 0);
196             }
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"));
200                 INTVAL i;
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)
206                         RETURN(INTVAL 0);
207                 }
209                 RETURN(INTVAL 1);
210             }
211             else if (max_severity > 0 || min_severity > 0) {
212                 RETURN(INTVAL 1);
213             }
215             RETURN(INTVAL 1);
216         }
218         RETURN(INTVAL 0);
219     }
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.
227 =cut
231     METHOD min_severity(INTVAL severity :optional, INTVAL have_severity :opt_flag) {
232         Parrot_ExceptionHandler_attributes * const attrs =
233                     PARROT_EXCEPTIONHANDLER(SELF);
235         if (have_severity)
236             attrs->min_severity = severity;
237         else
238             severity = attrs->min_severity;
240         RETURN(INTVAL severity);
241     }
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.
249 =cut
253     METHOD max_severity(INTVAL severity :optional, INTVAL have_severity :opt_flag) {
254         Parrot_ExceptionHandler_attributes * const attrs =
255                     PARROT_EXCEPTIONHANDLER(SELF);
257         if (have_severity)
258             attrs->max_severity = severity;
259         else
260             severity = attrs->max_severity;
262         RETURN(INTVAL severity);
263     }
267 =item C<METHOD handle_types(PMC *types :slurpy)>
269 Set the exception types that the ExceptionHandler will handle.
271 =cut
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
280                 ? types
281                 : PMCNULL;
282     }
286 =item C<METHOD handle_types_except(PMC *types :slurpy)>
288 Set the exception types that the ExceptionHandler will not handle.
290 =cut
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
299                 ? types
300                 : PMCNULL;
301     }
307 =back
309 =cut
314  * Local variables:
315  *   c-file-style: "parrot"
316  * End:
317  * vim: expandtab shiftwidth=4:
318  */