9fc6fe468659703bdb3829d7f1014fefe221a072
2 ** error.c - Exception class
4 ** See Copyright Notice in mruby.h
11 #include "mruby/array.h"
12 #include "mruby/irep.h"
13 #include "mruby/proc.h"
14 #include "mruby/string.h"
15 #include "mruby/variable.h"
16 #include "mruby/debug.h"
17 #include "mruby/error.h"
18 #include "mruby/class.h"
19 #include "mrb_throw.h"
22 exc_mesg_set(mrb_state
*mrb
, struct RException
*exc
, mrb_value mesg
)
24 exc
->flags
|= MRB_EXC_MESG_INIT_FLAG
;
26 mrb_field_write_barrier_value(mrb
, (struct RBasic
*)exc
, mesg
);
30 exc_mesg_get(mrb_state
*mrb
, struct RException
*exc
)
32 return (exc
->flags
& MRB_EXC_MESG_INIT_FLAG
) != 0 ? exc
->mesg
: mrb_nil_value();
36 mrb_exc_new(mrb_state
*mrb
, struct RClass
*c
, const char *ptr
, long len
)
38 mrb_value arg
= mrb_str_new(mrb
, ptr
, len
);
39 return mrb_obj_new(mrb
, c
, 1, &arg
);
43 mrb_exc_new_str(mrb_state
*mrb
, struct RClass
* c
, mrb_value str
)
45 str
= mrb_str_to_str(mrb
, str
);
46 return mrb_obj_new(mrb
, c
, 1, &str
);
51 * Exception.new(msg = nil) -> exception
53 * Construct a new Exception object, optionally passing in
58 exc_initialize(mrb_state
*mrb
, mrb_value exc
)
62 if (mrb_get_args(mrb
, "|o", &mesg
) == 1) {
63 exc_mesg_set(mrb
, mrb_exc_ptr(exc
), mesg
);
69 * Document-method: exception
72 * exc.exception(string) -> an_exception or exc
74 * With no argument, or if the argument is the same as the receiver,
75 * return the receiver. Otherwise, create a new
76 * exception object of the same class as the receiver, but with a
77 * message equal to <code>string.to_str</code>.
82 exc_exception(mrb_state
*mrb
, mrb_value self
)
88 argc
= mrb_get_args(mrb
, "|o", &a
);
89 if (argc
== 0) return self
;
90 if (mrb_obj_equal(mrb
, self
, a
)) return self
;
91 exc
= mrb_obj_clone(mrb
, self
);
92 exc_mesg_set(mrb
, mrb_exc_ptr(exc
), a
);
99 * exception.to_s -> string
101 * Returns exception's message (or the name of the exception if
102 * no message is set).
106 exc_to_s(mrb_state
*mrb
, mrb_value exc
)
108 mrb_value mesg
= exc_mesg_get(mrb
, mrb_exc_ptr(exc
));
111 if (!mrb_string_p(mesg
)) {
112 return mrb_str_new_cstr(mrb
, mrb_obj_classname(mrb
, exc
));
114 p
= mrb_obj_ptr(mesg
);
116 p
->c
= mrb
->string_class
;
123 * exception.message -> string
125 * Returns the result of invoking <code>exception.to_s</code>.
126 * Normally this returns the exception's message or name. By
127 * supplying a to_str method, exceptions are agreeing to
128 * be used where Strings are expected.
132 exc_message(mrb_state
*mrb
, mrb_value exc
)
134 return mrb_funcall(mrb
, exc
, "to_s", 0);
139 * exception.inspect -> string
141 * Returns this exception's file name, line number,
142 * message and class name.
143 * If file name or line number is not set,
144 * returns message and class name.
148 exc_inspect(mrb_state
*mrb
, mrb_value exc
)
150 mrb_value str
, mesg
, file
, line
;
151 mrb_bool append_mesg
;
153 mesg
= exc_mesg_get(mrb
, mrb_exc_ptr(exc
));
154 file
= mrb_attr_get(mrb
, exc
, mrb_intern_lit(mrb
, "file"));
155 line
= mrb_attr_get(mrb
, exc
, mrb_intern_lit(mrb
, "line"));
157 append_mesg
= !mrb_nil_p(mesg
);
159 mesg
= mrb_obj_as_string(mrb
, mesg
);
160 append_mesg
= RSTRING_LEN(mesg
) > 0;
163 if (!mrb_nil_p(file
) && !mrb_nil_p(line
)) {
164 str
= mrb_str_dup(mrb
, file
);
165 mrb_str_cat_lit(mrb
, str
, ":");
166 mrb_str_append(mrb
, str
, line
);
167 mrb_str_cat_lit(mrb
, str
, ": ");
169 mrb_str_append(mrb
, str
, mesg
);
170 mrb_str_cat_lit(mrb
, str
, " (");
172 mrb_str_cat_cstr(mrb
, str
, mrb_obj_classname(mrb
, exc
));
174 mrb_str_cat_lit(mrb
, str
, ")");
178 const char *cname
= mrb_obj_classname(mrb
, exc
);
179 str
= mrb_str_new_cstr(mrb
, cname
);
180 mrb_str_cat_lit(mrb
, str
, ": ");
182 mrb_str_append(mrb
, str
, mesg
);
185 mrb_str_cat_cstr(mrb
, str
, cname
);
193 exc_debug_info(mrb_state
*mrb
, struct RObject
*exc
)
195 mrb_callinfo
*ci
= mrb
->c
->ci
;
196 mrb_code
*pc
= ci
->pc
;
198 mrb_obj_iv_set(mrb
, exc
, mrb_intern_lit(mrb
, "ciidx"), mrb_fixnum_value((mrb_int
)(ci
- mrb
->c
->cibase
)));
199 while (ci
>= mrb
->c
->cibase
) {
200 mrb_code
*err
= ci
->err
;
202 if (!err
&& pc
) err
= pc
- 1;
203 if (err
&& ci
->proc
&& !MRB_PROC_CFUNC_P(ci
->proc
)) {
204 mrb_irep
*irep
= ci
->proc
->body
.irep
;
206 int32_t const line
= mrb_debug_get_line(irep
, (uint32_t)(err
- irep
->iseq
));
207 char const* file
= mrb_debug_get_filename(irep
, (uint32_t)(err
- irep
->iseq
));
208 if (line
!= -1 && file
) {
209 mrb_obj_iv_set(mrb
, exc
, mrb_intern_lit(mrb
, "file"), mrb_str_new_cstr(mrb
, file
));
210 mrb_obj_iv_set(mrb
, exc
, mrb_intern_lit(mrb
, "line"), mrb_fixnum_value(line
));
220 mrb_exc_raise(mrb_state
*mrb
, mrb_value exc
)
222 mrb
->exc
= mrb_obj_ptr(exc
);
223 if (!mrb
->out_of_memory
) {
224 exc_debug_info(mrb
, mrb
->exc
);
234 mrb_raise(mrb_state
*mrb
, struct RClass
*c
, const char *msg
)
237 mesg
= mrb_str_new_cstr(mrb
, msg
);
238 mrb_exc_raise(mrb
, mrb_exc_new_str(mrb
, c
, mesg
));
242 mrb_vformat(mrb_state
*mrb
, const char *format
, va_list ap
)
244 const char *p
= format
;
247 mrb_value ary
= mrb_ary_new_capa(mrb
, 4);
255 mrb_ary_push(mrb
, ary
, mrb_str_new(mrb
, b
, size
));
256 mrb_ary_push(mrb
, ary
, va_arg(ap
, mrb_value
));
260 else if (c
== '\\') {
263 mrb_ary_push(mrb
, ary
, mrb_str_new(mrb
, b
, size
));
264 mrb_ary_push(mrb
, ary
, mrb_str_new(mrb
, p
, 1));
273 return mrb_str_new_cstr(mrb
, format
);
277 mrb_ary_push(mrb
, ary
, mrb_str_new(mrb
, b
, size
));
278 return mrb_ary_join(mrb
, ary
, mrb_str_new(mrb
,NULL
,0));
283 mrb_format(mrb_state
*mrb
, const char *format
, ...)
288 va_start(ap
, format
);
289 str
= mrb_vformat(mrb
, format
, ap
);
296 mrb_raisef(mrb_state
*mrb
, struct RClass
*c
, const char *fmt
, ...)
302 mesg
= mrb_vformat(mrb
, fmt
, args
);
304 mrb_exc_raise(mrb
, mrb_exc_new_str(mrb
, c
, mesg
));
308 mrb_name_error(mrb_state
*mrb
, mrb_sym id
, const char *fmt
, ...)
315 argv
[0] = mrb_vformat(mrb
, fmt
, args
);
318 argv
[1] = mrb_symbol_value(id
);
319 exc
= mrb_obj_new(mrb
, E_NAME_ERROR
, 2, argv
);
320 mrb_exc_raise(mrb
, exc
);
324 mrb_warn(mrb_state
*mrb
, const char *fmt
, ...)
331 str
= mrb_vformat(mrb
, fmt
, ap
);
332 fputs("warning: ", stderr
);
333 fwrite(RSTRING_PTR(str
), RSTRING_LEN(str
), 1, stderr
);
339 mrb_bug(mrb_state
*mrb
, const char *fmt
, ...)
346 str
= mrb_vformat(mrb
, fmt
, ap
);
347 fputs("bug: ", stderr
);
348 fwrite(RSTRING_PTR(str
), RSTRING_LEN(str
), 1, stderr
);
355 set_backtrace(mrb_state
*mrb
, mrb_value info
, mrb_value bt
)
357 mrb_funcall(mrb
, info
, "set_backtrace", 1, bt
);
361 make_exception(mrb_state
*mrb
, int argc
, const mrb_value
*argv
, mrb_bool isstr
)
366 mesg
= mrb_nil_value();
371 if (mrb_nil_p(argv
[0]))
374 mesg
= mrb_check_string_type(mrb
, argv
[0]);
375 if (!mrb_nil_p(mesg
)) {
376 mesg
= mrb_exc_new_str(mrb
, E_RUNTIME_ERROR
, mesg
);
388 mrb_sym exc
= mrb_intern_lit(mrb
, "exception");
389 if (mrb_respond_to(mrb
, argv
[0], exc
)) {
390 mesg
= mrb_funcall_argv(mrb
, argv
[0], exc
, n
, argv
+1);
394 mrb_raise(mrb
, E_TYPE_ERROR
, "exception class/object expected");
400 mrb_raisef(mrb
, E_ARGUMENT_ERROR
, "wrong number of arguments (%S for 0..3)", mrb_fixnum_value(argc
));
404 if (!mrb_obj_is_kind_of(mrb
, mesg
, mrb
->eException_class
))
405 mrb_raise(mrb
, E_TYPE_ERROR
, "exception object expected");
407 set_backtrace(mrb
, mesg
, argv
[2]);
414 mrb_make_exception(mrb_state
*mrb
, int argc
, const mrb_value
*argv
)
416 return make_exception(mrb
, argc
, argv
, TRUE
);
420 mrb_sys_fail(mrb_state
*mrb
, const char *mesg
)
426 if (mrb_class_defined(mrb
, "SystemCallError")) {
427 sce
= mrb_class_get(mrb
, "SystemCallError");
429 mrb_funcall(mrb
, mrb_obj_value(sce
), "_sys_fail", 2, mrb_fixnum_value(no
), mrb_str_new_cstr(mrb
, mesg
));
432 mrb_funcall(mrb
, mrb_obj_value(sce
), "_sys_fail", 1, mrb_fixnum_value(no
));
436 mrb_raise(mrb
, E_RUNTIME_ERROR
, mesg
);
441 mrb_no_method_error(mrb_state
*mrb
, mrb_sym id
, mrb_int argc
, const mrb_value
*argv
, char const* fmt
, ...)
447 exc
= mrb_funcall(mrb
, mrb_obj_value(E_NOMETHOD_ERROR
), "new", 3,
448 mrb_vformat(mrb
, fmt
, ap
), mrb_symbol_value(id
),
449 mrb_ary_new_from_values(mrb
, argc
, argv
));
451 mrb_exc_raise(mrb
, exc
);
455 mrb_init_exception(mrb_state
*mrb
)
457 struct RClass
*exception
, *runtime_error
, *script_error
;
459 mrb
->eException_class
= exception
= mrb_define_class(mrb
, "Exception", mrb
->object_class
); /* 15.2.22 */
460 MRB_SET_INSTANCE_TT(exception
, MRB_TT_EXCEPTION
);
461 mrb_define_class_method(mrb
, exception
, "exception", mrb_instance_new
, MRB_ARGS_ANY());
462 mrb_define_method(mrb
, exception
, "exception", exc_exception
, MRB_ARGS_ANY());
463 mrb_define_method(mrb
, exception
, "initialize", exc_initialize
, MRB_ARGS_ANY());
464 mrb_define_method(mrb
, exception
, "to_s", exc_to_s
, MRB_ARGS_NONE());
465 mrb_define_method(mrb
, exception
, "message", exc_message
, MRB_ARGS_NONE());
466 mrb_define_method(mrb
, exception
, "inspect", exc_inspect
, MRB_ARGS_NONE());
467 mrb_define_method(mrb
, exception
, "backtrace", mrb_exc_backtrace
, MRB_ARGS_NONE());
469 mrb
->eStandardError_class
= mrb_define_class(mrb
, "StandardError", mrb
->eException_class
); /* 15.2.23 */
470 runtime_error
= mrb_define_class(mrb
, "RuntimeError", mrb
->eStandardError_class
); /* 15.2.28 */
471 mrb
->nomem_err
= mrb_obj_ptr(mrb_exc_new_str(mrb
, runtime_error
, mrb_str_new_lit(mrb
, "Out of memory")));
472 script_error
= mrb_define_class(mrb
, "ScriptError", mrb
->eException_class
); /* 15.2.37 */
473 mrb_define_class(mrb
, "SyntaxError", script_error
); /* 15.2.38 */
474 mrb_define_class(mrb
, "SystemStackError", exception
);