summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--README.md7
-rw-r--r--include/mruby/error.h3
-rw-r--r--mrbgems/mruby-sprintf/src/sprintf.c1
-rw-r--r--src/backtrace.c36
-rw-r--r--src/class.c29
-rw-r--r--src/error.c4
-rw-r--r--src/vm.c4
-rw-r--r--tasks/mrbgem_spec.rake2
-rw-r--r--tasks/mrbgems_test.rake14
-rw-r--r--test/init_mrbtest.c2
-rw-r--r--test/mrbtest.rake19
12 files changed, 85 insertions, 37 deletions
diff --git a/AUTHORS b/AUTHORS
index 85d117f31..36eca92b2 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -17,3 +17,4 @@ Original Authors "mruby developers" are:
Jun Hiroe
Narihiro Nakamura
Yuichi Nishiwaki
+ Tatsuhiko Kubo
diff --git a/README.md b/README.md
index 7386f28bb..f7633019f 100644
--- a/README.md
+++ b/README.md
@@ -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.
-
[![Build Status](https://travis-ci.org/mruby/mruby.png?branch=master)](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 */
diff --git a/src/vm.c b/src/vm.c
index f11caedd7..13aa7c226 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -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