diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 1998-05-06 03:09:03 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 1998-05-06 03:09:03 +0000 |
commit | 6b7b84edc7168786408b0757e2eb53728d1b71a6 (patch) | |
tree | 299c41408ef82854a829327d1f8d5c4cc8cf6a8c /eval.c | |
parent | 53118356b53259b456aabc11fb1212d965251fc4 (diff) |
new exception model
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/v1_1r@202 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 180 |
1 files changed, 100 insertions, 80 deletions
@@ -354,7 +354,7 @@ rb_attr(klass, id, read, write, ex) } static ID init, eqq, each, aref, aset, match; -VALUE errinfo = Qnil, errat = Qnil; +VALUE errinfo = Qnil; extern NODE *eval_tree0; extern NODE *eval_tree; extern int nerrs; @@ -362,7 +362,6 @@ extern int nerrs; extern VALUE mKernel; extern VALUE cModule; extern VALUE eFatal; -extern VALUE eDefaultRescue; extern VALUE eStandardError; extern VALUE eInterrupt; extern VALUE eSystemExit; @@ -453,15 +452,15 @@ new_dvar(id, value) { NEWOBJ(vars, struct RVarmap); OBJSETUP(vars, 0, T_VARMAP); + vars->id = id; + vars->val = value; + vars->next = the_dyna_vars; if (id == 0) { vars->id = (ID)value; vars->val = 0; - vars->next = the_dyna_vars; the_dyna_vars = vars; } else if (the_dyna_vars) { - vars->id = id; - vars->val = value; vars->next = the_dyna_vars->next; the_dyna_vars->next = vars; } @@ -504,12 +503,14 @@ dyna_var_asgn(id, value) { struct RVarmap *vars = the_dyna_vars; - while (vars) { - if (vars->id == id) { - vars->val = value; - return value; + if (id) { + while (vars) { + if (vars->id == id) { + vars->val = value; + return value; + } + vars = vars->next; } - vars = vars->next; } new_dvar(id, value); return value; @@ -719,14 +720,31 @@ error_pos() } } +static VALUE +get_backtrace(info) + VALUE info; +{ + if (NIL_P(info)) return Qnil; + return rb_funcall(info, rb_intern("backtrace"), 0); +} + +static void +set_backtrace(info, bt) + VALUE info, bt; +{ + rb_funcall(info, rb_intern("set_backtrace"), 1, bt); +} + static void error_print() { + VALUE errat; VALUE eclass; VALUE einfo; if (NIL_P(errinfo)) return; + errat = get_backtrace(errinfo); if (!NIL_P(errat)) { VALUE mesg = RARRAY(errat)->ptr[0]; @@ -909,7 +927,6 @@ ruby_run() if (nerrs > 0) exit(nerrs); init_stack(); - errat = Qnil; /* clear for execution */ PUSH_TAG(PROT_NONE); PUSH_ITER(ITER_NOT); @@ -985,19 +1002,20 @@ static void compile_error(at) char *at; { + VALUE str; char *mesg; int len; mesg = str2cstr(errinfo, &len); nerrs = 0; - errinfo = exc_new2(eSyntaxError, "compile error"); + str = str_new2("compile error"); if (at) { - str_cat(errinfo, " in ", 4); - str_cat(errinfo, at, strlen(at)); + str_cat(str, " in ", 4); + str_cat(str, at, strlen(at)); } - str_cat(errinfo, "\n", 1); - str_cat(errinfo, mesg, len); - rb_raise(errinfo); + str_cat(str, "\n", 1); + str_cat(str, mesg, len); + rb_raise(exc_new3(eSyntaxError, str)); } VALUE @@ -1797,7 +1815,7 @@ rb_eval(self, node) case NODE_RESCUE: retry_entry: { - volatile VALUE e_info = errinfo, e_at = errat; + volatile VALUE e_info = errinfo; PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { @@ -1817,7 +1835,6 @@ rb_eval(self, node) POP_TAG(); if (state == 0) { errinfo = e_info; - errat = e_at; } else if (state == TAG_RETRY) { state = 0; @@ -2664,36 +2681,25 @@ static volatile voidfn rb_longjmp; static VALUE make_backtrace _((void)); -static VALUE -check_errat(val) - VALUE val; +static void +rb_longjmp(tag, mesg) + int tag; + VALUE mesg; { - int i; - static char *err = "value of $@ must be Array of String"; + VALUE at; - if (!NIL_P(val)) { - int t = TYPE(val); - - if (t == T_STRING) return ary_new3(1, val); - if (t != T_ARRAY) { - TypeError(err); - } - for (i=0;i<RARRAY(val)->len;i++) { - if (TYPE(RARRAY(val)->ptr[i]) != T_STRING) { - TypeError(err); - } - } + if (NIL_P(mesg)) mesg = errinfo; + if (NIL_P(mesg)) { + mesg = exc_new(eRuntimeError, 0, 0); } - return val; -} -static void -rb_longjmp(tag, mesg, at) - int tag; - VALUE mesg, at; -{ - if (NIL_P(errinfo) && NIL_P(mesg)) { - errinfo = exc_new(eRuntimeError, 0, 0); + at = get_backtrace(mesg); + if (NIL_P(at) && sourcefile && !NIL_P(mesg)) { + at = make_backtrace(); + set_backtrace(mesg, at); + } + if (!NIL_P(mesg)) { + errinfo = mesg; } if (debug && !NIL_P(errinfo)) { @@ -2701,16 +2707,6 @@ rb_longjmp(tag, mesg, at) rb_class2name(CLASS_OF(errinfo)), sourcefile, sourceline); } - if (!NIL_P(at)) { - errat = check_errat(at); - } - else if (sourcefile && (NIL_P(errat) || !NIL_P(mesg))) { - errat = make_backtrace(); - } - - if (!NIL_P(mesg)) { - errinfo = mesg; - } trap_restore_mask(); if (trace_func && tag != TAG_FATAL) { @@ -2724,14 +2720,14 @@ void rb_raise(mesg) VALUE mesg; { - rb_longjmp(TAG_RAISE, mesg, Qnil); + rb_longjmp(TAG_RAISE, mesg); } void rb_fatal(mesg) VALUE mesg; { - rb_longjmp(TAG_FATAL, mesg, Qnil); + rb_longjmp(TAG_FATAL, mesg); } void @@ -2755,8 +2751,8 @@ f_raise(argc, argv) case 1: mesg = arg1; break; - case 2: case 3: + case 2: etype = arg1; mesg = arg2; break; @@ -2769,11 +2765,15 @@ f_raise(argc, argv) else if (TYPE(mesg) == T_STRING) { mesg = exc_new3(eRuntimeError, mesg); } + if (!obj_is_kind_of(mesg, eException)) { + TypeError("casting non-exception"); + } + set_backtrace(mesg, arg3); } PUSH_FRAME(); /* fake frame */ *the_frame = *_frame.prev->prev; - rb_longjmp(TAG_RAISE, mesg, arg3); + rb_longjmp(TAG_RAISE, mesg); POP_FRAME(); } @@ -3037,7 +3037,7 @@ handle_rescue(self, node) TMP_PROTECT; if (!node->nd_args) { - return obj_is_kind_of(errinfo, eDefaultRescue); + return obj_is_kind_of(errinfo, eStandardError); } PUSH_ITER(ITER_NOT); @@ -3060,13 +3060,14 @@ rb_rescue(b_proc, data1, r_proc, data2) { int state; volatile VALUE result; + volatile VALUE e_info = errinfo; PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { retry_entry: result = (*b_proc)(data1); } - else if (state == TAG_RAISE && obj_is_kind_of(errinfo, eDefaultRescue)) { + else if (state == TAG_RAISE && obj_is_kind_of(errinfo, eStandardError)) { if (r_proc) { PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { @@ -3083,7 +3084,7 @@ rb_rescue(b_proc, data1, r_proc, data2) state = 0; } if (state == 0) { - errat = Qnil; + errinfo = e_info; } } POP_TAG(); @@ -3826,9 +3827,11 @@ eval(self, src, scope, file, line) sourcefile = filesave; sourceline = linesave; if (state) { - VALUE err; - if (state == TAG_RAISE) { + VALUE err; + VALUE errat; + + errat = get_backtrace(errinfo); if (strcmp(file, "(eval)") == 0) { if (sourceline > 1) { err = RARRAY(errat)->ptr[0]; @@ -3841,7 +3844,7 @@ eval(self, src, scope, file, line) errat = Qnil; rb_raise(exc_new3(CLASS_OF(errinfo), err)); } - rb_raise(Qnil); + rb_raise(errinfo); } JUMP_TAG(state); } @@ -4062,6 +4065,7 @@ f_load(obj, fname) file = find_file(RSTRING(fname)->ptr); if (!file) LoadError("No such file to load -- %s", RSTRING(fname)->ptr); + PUSH_VARS(); PUSH_TAG(PROT_NONE); PUSH_CLASS(); the_class = cObject; @@ -4097,6 +4101,7 @@ f_load(obj, fname) POP_SCOPE(); POP_CLASS(); POP_TAG(); + POP_VARS(); if (nerrs > 0) { rb_raise(errinfo); } @@ -4472,7 +4477,24 @@ obj_extend(argc, argv, obj) VALUE f_trace_var(); VALUE f_untrace_var(); -extern void rb_str_setter(); +static void +errinfo_setter(val, id, var) + VALUE val; + ID id; + VALUE *var; +{ + if (!obj_is_kind_of(val, eException)) { + TypeError("assigning non-exception to $!"); + } + *var = val; +} + +static VALUE +errat_getter(id) + ID id; +{ + return get_backtrace(errinfo); +} static void errat_setter(val, id, var) @@ -4480,7 +4502,10 @@ errat_setter(val, id, var) ID id; VALUE *var; { - *var = check_errat(val); + if (NIL_P(errinfo)) { + ArgError("$! not set"); + } + set_backtrace(errinfo, val); } VALUE f_global_variables(); @@ -4589,8 +4614,8 @@ Init_eval() rb_global_variable((VALUE*)&eval_tree); rb_global_variable((VALUE*)&the_dyna_vars); - rb_define_hooked_variable("$@", &errat, 0, errat_setter); - rb_define_variable("$!", &errinfo); + rb_define_virtual_variable("$@", errat_getter, errat_setter); + rb_define_hooked_variable("$!", &errinfo, 0, errinfo_setter); rb_define_global_function("eval", f_eval, -1); rb_define_global_function("iterator?", f_iterator_p, 0); @@ -5253,7 +5278,7 @@ struct thread { char *file; int line; - VALUE errat, errinfo; + VALUE errinfo; VALUE last_status; VALUE last_line; VALUE last_match; @@ -5315,7 +5340,6 @@ thread_mark(th) gc_mark(th->scope); gc_mark(th->dyna_vars); - gc_mark(th->errat); gc_mark(th->errinfo); gc_mark(th->last_line); gc_mark(th->last_match); @@ -5398,7 +5422,6 @@ thread_save_context(th) th->misc = scope_vmode | (trap_immediate<<8); th->iter = the_iter; th->tag = prot_tag; - th->errat = errat; th->errinfo = errinfo; th->last_status = last_status; th->last_line = lastline_get(); @@ -5459,7 +5482,6 @@ thread_restore_context(th, exit) trap_immediate = th->misc>>8; the_iter = th->iter; prot_tag = th->tag; - errat = th->errat; errinfo = th->errinfo; last_status = th->last_status; safe_level = th->safe; @@ -6051,7 +6073,6 @@ thread_alloc() th->status = 0; th->result = 0; th->errinfo = Qnil; - th->errat = Qnil; th->stk_ptr = 0; th->stk_len = 0; @@ -6068,7 +6089,6 @@ thread_alloc() th->block = 0; th->iter = 0; th->tag = 0; - th->errat = 0; th->errinfo = 0; th->last_status = 0; th->last_line = 0; @@ -6157,7 +6177,6 @@ thread_create(fn, arg) if (state == TAG_FATAL || obj_is_kind_of(errinfo, eSystemExit)) { /* fatal error or global exit within this thread */ /* need to stop whole script */ - main_thread->errat = errat; main_thread->errinfo = errinfo; thread_cleanup(); } @@ -6165,7 +6184,6 @@ thread_create(fn, arg) f_abort(); } else { - curr_thread->errat = errat; curr_thread->errinfo = errinfo; } } @@ -6199,9 +6217,11 @@ thread_value(thread) thread_join(0, thread); if (!NIL_P(th->errinfo)) { - errat = make_backtrace(); - ary_unshift(errat, ary_entry(th->errat, 0)); - sourcefile = 0; /* kludge to print errat */ + VALUE oldbt = get_backtrace(th->errinfo); + VALUE errat = make_backtrace(); + + ary_unshift(errat, ary_entry(oldbt, 0)); + set_backtrace(th->errinfo, errat); rb_raise(th->errinfo); } |