diff options
| -rw-r--r-- | AUTHORS | 1 | ||||
| -rw-r--r-- | README.md | 7 | ||||
| -rw-r--r-- | include/mruby/error.h | 3 | ||||
| -rw-r--r-- | mrbgems/mruby-sprintf/src/sprintf.c | 1 | ||||
| -rw-r--r-- | src/backtrace.c | 36 | ||||
| -rw-r--r-- | src/class.c | 29 | ||||
| -rw-r--r-- | src/error.c | 4 | ||||
| -rw-r--r-- | src/vm.c | 4 | ||||
| -rw-r--r-- | tasks/mrbgem_spec.rake | 2 | ||||
| -rw-r--r-- | tasks/mrbgems_test.rake | 14 | ||||
| -rw-r--r-- | test/init_mrbtest.c | 2 | ||||
| -rw-r--r-- | test/mrbtest.rake | 19 |
12 files changed, 85 insertions, 37 deletions
@@ -17,3 +17,4 @@ Original Authors "mruby developers" are: Jun Hiroe Narihiro Nakamura Yuichi Nishiwaki + Tatsuhiko Kubo @@ -1,10 +1,3 @@ -# !!Notice!! - This is a preliminary release for internal team review. - The URLs and addresses described below are not available yet. - The official release will be announced later. - Any suggestions for modification are welcome. - Delays in replies are to be expected. Sorry in advance. - [](https://travis-ci.org/mruby/mruby) ## What's mruby diff --git a/include/mruby/error.h b/include/mruby/error.h index b04dc1082..96c4092b5 100644 --- a/include/mruby/error.h +++ b/include/mruby/error.h @@ -13,5 +13,8 @@ mrb_value mrb_make_exception(mrb_state *mrb, int argc, mrb_value *argv); mrb_value mrb_format(mrb_state *mrb, const char *format, ...); void mrb_exc_print(mrb_state *mrb, struct RObject *exc); void mrb_longjmp(mrb_state *mrb); +void mrb_print_backtrace(mrb_state *mrb); +mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc); +mrb_value mrb_get_backtrace(mrb_state *mrb); #endif /* MRUBY_ERROR_H */ diff --git a/mrbgems/mruby-sprintf/src/sprintf.c b/mrbgems/mruby-sprintf/src/sprintf.c index 64b9f0787..b20cbe1df 100644 --- a/mrbgems/mruby-sprintf/src/sprintf.c +++ b/mrbgems/mruby-sprintf/src/sprintf.c @@ -654,6 +654,7 @@ retry: case '\n': case '\0': p--; + break; case '%': if (flags != FNONE) { diff --git a/src/backtrace.c b/src/backtrace.c index a221d5e5c..6469fc069 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -12,6 +12,7 @@ #include "mruby/string.h" #include "mruby/class.h" #include "mruby/debug.h" +#include "mruby/error.h" typedef void (*output_stream_func)(mrb_state*, void*, int, const char*, ...); @@ -57,14 +58,12 @@ get_backtrace_i(mrb_state *mrb, void *stream, int level, const char *format, ... } static void -mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func func, void *stream) +output_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, output_stream_func func, void *stream) { mrb_callinfo *ci; - mrb_int ciidx; const char *filename, *method, *sep; int i, lineno, tracehead = 1; - ciidx = mrb_fixnum(mrb_obj_iv_get(mrb, exc, mrb_intern_lit(mrb, "ciidx"))); if (ciidx >= mrb->c->ciend - mrb->c->cibase) ciidx = 10; /* ciidx is broken... */ @@ -87,7 +86,7 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun pc = mrb->c->cibase[i+1].pc - 1; } else { - pc = (mrb_code*)mrb_cptr(mrb_obj_iv_get(mrb, exc, mrb_intern_lit(mrb, "lastpc"))); + pc = pc0; } filename = mrb_debug_get_filename(irep, pc - irep->iseq); lineno = mrb_debug_get_line(irep, pc - irep->iseq); @@ -129,6 +128,14 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun } } +static void +exc_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func func, void *stream) +{ + output_backtrace(mrb, mrb_fixnum(mrb_obj_iv_get(mrb, exc, mrb_intern_lit(mrb, "ciidx"))), + (mrb_code*)mrb_cptr(mrb_obj_iv_get(mrb, exc, mrb_intern_lit(mrb, "lastpc"))), + func, stream); +} + /* mrb_print_backtrace/mrb_get_backtrace: function to retrieve backtrace information from the exception. @@ -140,17 +147,32 @@ void mrb_print_backtrace(mrb_state *mrb) { #ifdef ENABLE_STDIO - mrb_output_backtrace(mrb, mrb->exc, print_backtrace_i, (void*)stderr); + exc_output_backtrace(mrb, mrb->exc, print_backtrace_i, (void*)stderr); #endif } mrb_value -mrb_get_backtrace(mrb_state *mrb, mrb_value self) +mrb_exc_backtrace(mrb_state *mrb, mrb_value self) +{ + mrb_value ary; + + ary = mrb_ary_new(mrb); + exc_output_backtrace(mrb, mrb_obj_ptr(self), get_backtrace_i, (void*)mrb_ary_ptr(ary)); + + return ary; +} + +mrb_value +mrb_get_backtrace(mrb_state *mrb) { mrb_value ary; + mrb_callinfo *ci = mrb->c->ci; + mrb_code *pc = ci->pc; + mrb_int ciidx = ci - mrb->c->cibase - 1; + if (ciidx < 0) ciidx = 0; ary = mrb_ary_new(mrb); - mrb_output_backtrace(mrb, mrb_obj_ptr(self), get_backtrace_i, (void*)mrb_ary_ptr(ary)); + output_backtrace(mrb, ciidx, pc, get_backtrace_i, (void*)mrb_ary_ptr(ary)); return ary; } diff --git a/src/class.c b/src/class.c index ebe2bdb4a..84f8ea70e 100644 --- a/src/class.c +++ b/src/class.c @@ -731,8 +731,13 @@ boot_defclass(mrb_state *mrb, struct RClass *super) struct RClass *c; c = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_CLASS, mrb->class_class); - c->super = super ? super : mrb->object_class; - mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)super); + if (super) { + c->super = super; + mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)super); + } + else { + c->super = mrb->object_class; + } c->mt = kh_init(mt, mrb); return c; } @@ -1189,22 +1194,28 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod) mrb_sym name; mrb_value *a; int alen; - mrb_value inspect; + mrb_sym inspect; + mrb_value repr; mrb_get_args(mrb, "n*", &name, &a, &alen); - if (mrb_respond_to(mrb,mod,mrb_intern_lit(mrb, "inspect"))){ - inspect = mrb_funcall(mrb, mod, "inspect", 0); - if (RSTRING_LEN(inspect) > 64) { - inspect = mrb_any_to_s(mrb, mod); + inspect = mrb_intern_lit(mrb, "inspect"); + if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) { + /* method missing in inspect; avoid recursion */ + repr = mrb_any_to_s(mrb, mod); + } + else if (mrb_respond_to(mrb, mod, inspect)) { + repr = mrb_funcall_argv(mrb, mod, inspect, 0, 0); + if (RSTRING_LEN(repr) > 64) { + repr = mrb_any_to_s(mrb, mod); } } else { - inspect = mrb_any_to_s(mrb, mod); + repr = mrb_any_to_s(mrb, mod); } mrb_raisef(mrb, E_NOMETHOD_ERROR, "undefined method '%S' for %S", - mrb_sym2str(mrb, name), inspect); + mrb_sym2str(mrb, name), repr); /* not reached */ return mrb_nil_value(); } diff --git a/src/error.c b/src/error.c index 8d0ec67e0..26dc97166 100644 --- a/src/error.c +++ b/src/error.c @@ -431,8 +431,6 @@ mrb_sys_fail(mrb_state *mrb, const char *mesg) } } -mrb_value mrb_get_backtrace(mrb_state*, mrb_value); - void mrb_init_exception(mrb_state *mrb) { @@ -446,7 +444,7 @@ mrb_init_exception(mrb_state *mrb) mrb_define_method(mrb, e, "to_s", exc_to_s, MRB_ARGS_NONE()); mrb_define_method(mrb, e, "message", exc_message, MRB_ARGS_NONE()); mrb_define_method(mrb, e, "inspect", exc_inspect, MRB_ARGS_NONE()); - mrb_define_method(mrb, e, "backtrace", mrb_get_backtrace, MRB_ARGS_NONE()); + mrb_define_method(mrb, e, "backtrace", mrb_exc_backtrace, MRB_ARGS_NONE()); mrb->eStandardError_class = mrb_define_class(mrb, "StandardError", mrb->eException_class); /* 15.2.23 */ mrb_define_class(mrb, "RuntimeError", mrb->eStandardError_class); /* 15.2.28 */ @@ -1342,7 +1342,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int goto L_RAISE; } if (mrb->c->prev->ci == mrb->c->prev->cibase) { - mrb_value exc = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, mrb_str_new(mrb, "double resume", 13)); + mrb_value exc = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, mrb_str_new_lit(mrb, "double resume")); mrb->exc = mrb_obj_ptr(exc); goto L_RAISE; } @@ -2173,7 +2173,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int mrb_value mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) { - return mrb_context_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */ + return mrb_context_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */ } void diff --git a/tasks/mrbgem_spec.rake b/tasks/mrbgem_spec.rake index e9caf1d3a..6af28694e 100644 --- a/tasks/mrbgem_spec.rake +++ b/tasks/mrbgem_spec.rake @@ -62,7 +62,7 @@ module MRuby @test_objs = Dir.glob("#{dir}/test/*.{c,cpp,cxx,m,asm,S}").map do |f| objfile(f.relative_path_from(dir).to_s.pathmap("#{build_dir}/%X")) end - @test_preload = 'test/assert.rb' + @test_preload = nil # 'test/assert.rb' @test_args = {} @bins = [] diff --git a/tasks/mrbgems_test.rake b/tasks/mrbgems_test.rake index 166daf9c7..33f1fdb48 100644 --- a/tasks/mrbgems_test.rake +++ b/tasks/mrbgems_test.rake @@ -6,11 +6,15 @@ MRuby.each_target do file g.test_rbireps => [g.test_rbfiles].flatten + [g.build.mrbcfile] do |t| open(t.name, 'w') do |f| g.print_gem_test_header(f) - test_preload = [g.dir, MRUBY_ROOT].map {|dir| + test_preload = g.test_preload and [g.dir, MRUBY_ROOT].map {|dir| File.expand_path(g.test_preload, dir) }.find {|file| File.exist?(file) } - g.build.mrbc.run f, test_preload, "gem_test_irep_#{g.funcname}_preload" + if test_preload.nil? + f.puts %Q[extern const uint8_t mrbtest_assert_irep[];] + else + g.build.mrbc.run f, test_preload, "gem_test_irep_#{g.funcname}_preload" + end g.test_rbfiles.flatten.each_with_index do |rbfile, i| g.build.mrbc.run f, rbfile, "gem_test_irep_#{g.funcname}_#{i}" end @@ -31,7 +35,11 @@ MRuby.each_target do f.puts %Q[ if (mrb_test(val3)) {] f.puts %Q[ mrb_gv_set(mrb2, mrb_intern_lit(mrb2, "$mrbtest_verbose"), val3);] f.puts %Q[ }] - f.puts %Q[ mrb_load_irep(mrb2, gem_test_irep_#{g.funcname}_preload);] + if test_preload.nil? + f.puts %Q[ mrb_load_irep(mrb2, mrbtest_assert_irep);] + else + f.puts %Q[ mrb_load_irep(mrb2, gem_test_irep_#{g.funcname}_preload);] + end f.puts %Q[ if (mrb2->exc) {] f.puts %Q[ mrb_p(mrb2, mrb_obj_value(mrb2->exc));] f.puts %Q[ exit(EXIT_FAILURE);] diff --git a/test/init_mrbtest.c b/test/init_mrbtest.c index 8d01624f0..717578dc8 100644 --- a/test/init_mrbtest.c +++ b/test/init_mrbtest.c @@ -2,6 +2,7 @@ #include "mruby.h" #include "mruby/irep.h" +extern const uint8_t mrbtest_assert_irep[]; extern const uint8_t mrbtest_irep[]; void mrbgemtest_init(mrb_state* mrb); @@ -9,6 +10,7 @@ void mrbgemtest_init(mrb_state* mrb); void mrb_init_mrbtest(mrb_state *mrb) { + mrb_load_irep(mrb, mrbtest_assert_irep); mrb_load_irep(mrb, mrbtest_irep); #ifndef DISABLE_GEMS mrbgemtest_init(mrb); diff --git a/test/mrbtest.rake b/test/mrbtest.rake index 0507981d6..35495889e 100644 --- a/test/mrbtest.rake +++ b/test/mrbtest.rake @@ -8,10 +8,11 @@ MRuby.each_target do mlib = clib.ext(exts.object) mrbs = Dir.glob("#{current_dir}/t/*.rb") init = "#{current_dir}/init_mrbtest.c" - asslib = "#{current_dir}/assert.rb" + ass_c = "#{current_build_dir}/assert.c" + ass_lib = ass_c.ext(exts.object) mrbtest_lib = libfile("#{current_build_dir}/mrbtest") - file mrbtest_lib => [mlib, gems.map(&:test_objs), gems.map { |g| g.test_rbireps.ext(exts.object) }].flatten do |t| + file mrbtest_lib => [mlib, ass_lib, gems.map(&:test_objs), gems.map { |g| g.test_rbireps.ext(exts.object) }].flatten do |t| archiver.run t.name, t.prerequisites end @@ -27,13 +28,21 @@ MRuby.each_target do end end - file mlib => [clib] - file clib => [mrbcfile, init, asslib] + mrbs do |t| + file ass_lib => ass_c + file ass_c => "#{current_dir}/assert.rb" do |t| + FileUtils.mkdir_p File.dirname t.name + open(t.name, 'w') do |f| + mrbc.run f, [t.prerequisites], 'mrbtest_assert_irep' + end + end + + file mlib => clib + file clib => [mrbcfile, init] + mrbs do |t| _pp "GEN", "*.rb", "#{clib.relative_path}" FileUtils.mkdir_p File.dirname(clib) open(clib, 'w') do |f| f.puts IO.read(init) - mrbc.run f, [asslib] + mrbs, 'mrbtest_irep' + mrbc.run f, mrbs, 'mrbtest_irep' gems.each do |g| f.puts %Q[void GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb_state *mrb);] end |
