summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--doc/api/mruby.h.md20
-rw-r--r--include/mruby/error.h12
-rw-r--r--mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c3
-rw-r--r--mrbgems/mruby-bin-mruby/tools/mruby/mruby.c5
-rw-r--r--mrbgems/mruby-error/mrbgem.rake10
-rw-r--r--mrbgems/mruby-error/src/exception.c100
-rw-r--r--mrbgems/mruby-error/test/exception.c59
-rw-r--r--mrbgems/mruby-error/test/exception.rb55
-rw-r--r--mrbgems/mruby-time/src/time.c4
-rw-r--r--mrblib/string.rb1
-rw-r--r--src/array.c6
-rw-r--r--src/class.c119
-rw-r--r--src/dump.c8
-rw-r--r--src/error.c9
-rw-r--r--src/fmt_fp.c2
-rw-r--r--src/range.c4
-rw-r--r--src/variable.c2
-rw-r--r--src/vm.c13
-rw-r--r--tasks/mruby_build.rake7
19 files changed, 373 insertions, 66 deletions
diff --git a/doc/api/mruby.h.md b/doc/api/mruby.h.md
index 8862fee2c..06bab2d56 100644
--- a/doc/api/mruby.h.md
+++ b/doc/api/mruby.h.md
@@ -43,20 +43,22 @@ Deletes `mrb_state`.
int mrb_get_args(mrb_state *mrb, const char *format, ...);
```
Retrieve arguments from `mrb_state`.
+When applicable, implicit conversions (such as `to_str`,
+`to_ary`, `to_hash`) are applied to received arguments.
Use it inside a function pointed by `mrb_func_t`.
-It returns number of function retrieved.
-`format` is a list of following format specifier:
+It returns the number of arguments retrieved.
+`format` is a list of following format specifiers:
char|mruby type|retrieve types|note
:---:|----------|--------------|---
`o`|`Object`|`mrb_value`|Could be used to retrieve any type of argument
`C`|`Class`/`Module`|`mrb_value`|
-`S`|`String`|`mrb_value`|
-`A`|`Array`|`mrb_value`|
-`H`|`Hash`|`mrb_value`|
-`s`|`String`|`char*`, `mrb_int`|
-`z`|`String`|`char*`|
-`a`|`Array`|`mrb_value*`, `mrb_int`|
+`S`|`String`|`mrb_value`|when ! follows, the value may be nil
+`A`|`Array`|`mrb_value`|when ! follows, the value may be nil
+`H`|`Hash`|`mrb_value`|when ! follows, the value may be nil
+`s`|`String`|`char*`, `mrb_int`|Receive two arguments; s! gives (NULL,0) for nil
+`z`|`String`|`char*`|NUL terminated string; z! gives NULL for nil
+`a`|`Array`|`mrb_value*`, `mrb_int`|Receive two arguments; a! gives (NULL,0) for nil
`f`|`Float`|`mrb_float`|
`i`|`Integer`|`mrb_int`|
`b`|boolean|`mrb_bool`|
@@ -118,7 +120,7 @@ mrb_value example_method(mrb_state* mrb, mrb_value self){
void mrb_example_gem_init(mrb_state* mrb) {
struct RClass *example_class;
example_class = mrb_define_class(mrb, "Example_Class", mrb->object_class);
- mrb_define_method(mrb, example_class, "example_method", example_method, MRB_ARGS_NONE());
+ mrb_define_method(mrb, example_class, "example_method", example_method, MRB_ARGS_NONE());
}
void mrb_example_gem_final(mrb_state* mrb) {
diff --git a/include/mruby/error.h b/include/mruby/error.h
index 52f6772bd..e3e2b25e2 100644
--- a/include/mruby/error.h
+++ b/include/mruby/error.h
@@ -24,11 +24,21 @@ MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value st
MRB_API mrb_value mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv);
MRB_API mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc);
MRB_API mrb_value mrb_get_backtrace(mrb_state *mrb);
-MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_int argc, const mrb_value *argv, const char *fmt, ...);
+MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...);
/* declaration for fail method */
MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value);
+/* functions defined in mruby-error mrbgem */
+MRB_API mrb_value mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state);
+MRB_API mrb_value mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
+ mrb_func_t ensure, mrb_value e_data);
+MRB_API mrb_value mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
+ mrb_func_t rescue, mrb_value r_data);
+MRB_API mrb_value mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
+ mrb_func_t rescue, mrb_value r_data,
+ mrb_int len, struct RClass **classes);
+
#if defined(__cplusplus)
} /* extern "C" { */
#endif
diff --git a/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c b/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c
index f27f87a5d..301dde1c6 100644
--- a/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c
+++ b/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c
@@ -161,8 +161,7 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
static void
cleanup(mrb_state *mrb, struct mrbc_args *args)
{
- if (args->outfile)
- mrb_free(mrb, (void*)args->outfile);
+ mrb_free(mrb, (void*)args->outfile);
mrb_close(mrb);
}
diff --git a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c b/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c
index 141ea151b..5ca744388 100644
--- a/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c
+++ b/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c
@@ -159,10 +159,9 @@ cleanup(mrb_state *mrb, struct _args *args)
{
if (args->rfp && args->rfp != stdin)
fclose(args->rfp);
- if (args->cmdline && !args->fname)
+ if (!args->fname)
mrb_free(mrb, args->cmdline);
- if (args->argv)
- mrb_free(mrb, args->argv);
+ mrb_free(mrb, args->argv);
mrb_close(mrb);
}
diff --git a/mrbgems/mruby-error/mrbgem.rake b/mrbgems/mruby-error/mrbgem.rake
new file mode 100644
index 000000000..b8281b17e
--- /dev/null
+++ b/mrbgems/mruby-error/mrbgem.rake
@@ -0,0 +1,10 @@
+MRuby::Gem::Specification.new('mruby-error') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'extensional error handling'
+
+ if build.cxx_abi_enabled?
+ @objs << build.compile_as_cxx("#{spec.dir}/src/exception.c", "#{spec.build_dir}/src/exception.cxx")
+ @objs.delete_if { |v| v == objfile("#{spec.build_dir}/src/exception") }
+ end
+end
diff --git a/mrbgems/mruby-error/src/exception.c b/mrbgems/mruby-error/src/exception.c
new file mode 100644
index 000000000..911fde0be
--- /dev/null
+++ b/mrbgems/mruby-error/src/exception.c
@@ -0,0 +1,100 @@
+#include "mruby.h"
+#include "mruby/throw.h"
+#include "mruby/error.h"
+
+MRB_API mrb_value
+mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state)
+{
+ struct mrb_jmpbuf *prev_jmp = mrb->jmp;
+ struct mrb_jmpbuf c_jmp;
+ mrb_value result = mrb_nil_value();
+
+ if (state) { *state = FALSE; }
+
+ MRB_TRY(&c_jmp) {
+ mrb->jmp = &c_jmp;
+ result = body(mrb, data);
+ mrb->jmp = prev_jmp;
+ } MRB_CATCH(&c_jmp) {
+ mrb->jmp = prev_jmp;
+ result = mrb_obj_value(mrb->exc);
+ mrb->exc = NULL;
+ if (state) { *state = TRUE; }
+ } MRB_END_EXC(&c_jmp);
+
+ mrb_gc_protect(mrb, result);
+ return result;
+}
+
+MRB_API mrb_value
+mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t ensure, mrb_value e_data)
+{
+ struct mrb_jmpbuf *prev_jmp = mrb->jmp;
+ struct mrb_jmpbuf c_jmp;
+ mrb_value result;
+
+ MRB_TRY(&c_jmp) {
+ mrb->jmp = &c_jmp;
+ result = body(mrb, b_data);
+ mrb->jmp = prev_jmp;
+ } MRB_CATCH(&c_jmp) {
+ mrb->jmp = prev_jmp;
+ ensure(mrb, e_data);
+ MRB_THROW(mrb->jmp); /* rethrow catched exceptions */
+ } MRB_END_EXC(&c_jmp);
+
+ ensure(mrb, e_data);
+ mrb_gc_protect(mrb, result);
+ return result;
+}
+
+MRB_API mrb_value
+mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
+ mrb_func_t rescue, mrb_value r_data)
+{
+ return mrb_rescue_exceptions(mrb, body, b_data, rescue, r_data, 1, &mrb->eStandardError_class);
+}
+
+MRB_API mrb_value
+mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t rescue, mrb_value r_data,
+ mrb_int len, struct RClass **classes)
+{
+ struct mrb_jmpbuf *prev_jmp = mrb->jmp;
+ struct mrb_jmpbuf c_jmp;
+ mrb_value result;
+ mrb_bool error_matched = FALSE;
+ mrb_int i;
+
+ MRB_TRY(&c_jmp) {
+ mrb->jmp = &c_jmp;
+ result = body(mrb, b_data);
+ mrb->jmp = prev_jmp;
+ } MRB_CATCH(&c_jmp) {
+ mrb->jmp = prev_jmp;
+
+ for (i = 0; i < len; ++i) {
+ if (mrb_obj_is_kind_of(mrb, mrb_obj_value(mrb->exc), classes[i])) {
+ error_matched = TRUE;
+ break;
+ }
+ }
+
+ if (!error_matched) { MRB_THROW(mrb->jmp); }
+
+ mrb->exc = NULL;
+ result = rescue(mrb, r_data);
+ } MRB_END_EXC(&c_jmp);
+
+ mrb_gc_protect(mrb, result);
+ return result;
+}
+
+void
+mrb_mruby_error_gem_init(mrb_state *mrb)
+{
+}
+
+void
+mrb_mruby_error_gem_final(mrb_state *mrb)
+{
+}
diff --git a/mrbgems/mruby-error/test/exception.c b/mrbgems/mruby-error/test/exception.c
new file mode 100644
index 000000000..2a943aaae
--- /dev/null
+++ b/mrbgems/mruby-error/test/exception.c
@@ -0,0 +1,59 @@
+#include "mruby.h"
+#include "mruby/error.h"
+#include "mruby/array.h"
+
+static mrb_value
+protect_cb(mrb_state *mrb, mrb_value b)
+{
+ return mrb_yield_argv(mrb, b, 0, NULL);
+}
+
+static mrb_value
+run_protect(mrb_state *mrb, mrb_value self)
+{
+ mrb_value b;
+ mrb_value ret[2];
+ mrb_bool state;
+ mrb_get_args(mrb, "&", &b);
+ ret[0] = mrb_protect(mrb, protect_cb, b, &state);
+ ret[1] = mrb_bool_value(state);
+ return mrb_ary_new_from_values(mrb, 2, ret);
+}
+
+static mrb_value
+run_ensure(mrb_state *mrb, mrb_value self)
+{
+ mrb_value b, e;
+ mrb_get_args(mrb, "oo", &b, &e);
+ return mrb_ensure(mrb, protect_cb, b, protect_cb, e);
+}
+
+static mrb_value
+run_rescue(mrb_state *mrb, mrb_value self)
+{
+ mrb_value b, r;
+ mrb_get_args(mrb, "oo", &b, &r);
+ return mrb_rescue(mrb, protect_cb, b, protect_cb, r);
+}
+
+static mrb_value
+run_rescue_exceptions(mrb_state *mrb, mrb_value self)
+{
+ mrb_value b, r;
+ struct RClass *cls[1];
+ mrb_get_args(mrb, "oo", &b, &r);
+ cls[0] = E_TYPE_ERROR;
+ return mrb_rescue_exceptions(mrb, protect_cb, b, protect_cb, r, 1, cls);
+}
+
+void
+mrb_mruby_error_gem_test(mrb_state *mrb)
+{
+ struct RClass *cls;
+
+ cls = mrb_define_class(mrb, "ExceptionTest", mrb->object_class);
+ mrb_define_module_function(mrb, cls, "mrb_protect", run_protect, MRB_ARGS_NONE() | MRB_ARGS_BLOCK());
+ mrb_define_module_function(mrb, cls, "mrb_ensure", run_ensure, MRB_ARGS_REQ(2));
+ mrb_define_module_function(mrb, cls, "mrb_rescue", run_rescue, MRB_ARGS_REQ(2));
+ mrb_define_module_function(mrb, cls, "mrb_rescue_exceptions", run_rescue_exceptions, MRB_ARGS_REQ(2));
+}
diff --git a/mrbgems/mruby-error/test/exception.rb b/mrbgems/mruby-error/test/exception.rb
new file mode 100644
index 000000000..0bbc2a0e7
--- /dev/null
+++ b/mrbgems/mruby-error/test/exception.rb
@@ -0,0 +1,55 @@
+assert 'mrb_protect' do
+ # no failure in protect returns [result, false]
+ assert_equal ['test', false] do
+ ExceptionTest.mrb_protect { 'test' }
+ end
+ # failure in protect returns [exception, true]
+ result = ExceptionTest.mrb_protect { raise 'test' }
+ assert_kind_of RuntimeError, result[0]
+ assert_true result[1]
+end
+
+assert 'mrb_ensure' do
+ a = false
+ assert_equal 'test' do
+ ExceptionTest.mrb_ensure Proc.new { 'test' }, Proc.new { a = true }
+ end
+ assert_true a
+
+ a = false
+ assert_raise RuntimeError do
+ ExceptionTest.mrb_ensure Proc.new { raise 'test' }, Proc.new { a = true }
+ end
+ assert_true a
+end
+
+assert 'mrb_rescue' do
+ assert_equal 'test' do
+ ExceptionTest.mrb_rescue Proc.new { 'test' }, Proc.new {}
+ end
+
+ class CustomExp < Exception
+ end
+
+ assert_raise CustomExp do
+ ExceptionTest.mrb_rescue Proc.new { raise CustomExp.new 'test' }, Proc.new { 'rescue' }
+ end
+
+ assert_equal 'rescue' do
+ ExceptionTest.mrb_rescue Proc.new { raise 'test' }, Proc.new { 'rescue' }
+ end
+end
+
+assert 'mrb_rescue_exceptions' do
+ assert_equal 'test' do
+ ExceptionTest.mrb_rescue_exceptions Proc.new { 'test' }, Proc.new {}
+ end
+
+ assert_raise RangeError do
+ ExceptionTest.mrb_rescue_exceptions Proc.new { raise RangeError.new 'test' }, Proc.new { 'rescue' }
+ end
+
+ assert_equal 'rescue' do
+ ExceptionTest.mrb_rescue_exceptions Proc.new { raise TypeError.new 'test' }, Proc.new { 'rescue' }
+ end
+end
diff --git a/mrbgems/mruby-time/src/time.c b/mrbgems/mruby-time/src/time.c
index 081e84c1c..c18ac7568 100644
--- a/mrbgems/mruby-time/src/time.c
+++ b/mrbgems/mruby-time/src/time.c
@@ -11,6 +11,10 @@
#include "mruby/class.h"
#include "mruby/data.h"
+#if !defined(__MINGW64__) && defined(_WIN32)
+# define llround(x) round(x)
+#endif
+
#if defined(__MINGW64__) || defined(__MINGW32__)
# include <sys/time.h>
#endif
diff --git a/mrblib/string.rb b/mrblib/string.rb
index ee097ad6d..23cf02e97 100644
--- a/mrblib/string.rb
+++ b/mrblib/string.rb
@@ -111,6 +111,7 @@ class String
def sub(*args, &block)
if args.size == 2
pre, post = split(args[0], 2)
+ return self unless post # The sub target wasn't found in the string
pre + args[1].__sub_replace(pre, args[0], post) + post
elsif args.size == 1 && block
split(args[0], 2).join(block.call(args[0]))
diff --git a/src/array.c b/src/array.c
index f48719310..0a99040c0 100644
--- a/src/array.c
+++ b/src/array.c
@@ -295,7 +295,7 @@ mrb_ary_plus(mrb_state *mrb, mrb_value self)
mrb_get_args(mrb, "a", &ptr, &blen);
if (ARY_MAX_SIZE - blen < a1->len) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
}
a2 = ary_new_capa(mrb, a1->len + blen);
array_copy(a2->ptr, a1->ptr, a1->len);
@@ -349,7 +349,7 @@ mrb_ary_times(mrb_state *mrb, mrb_value self)
}
if (times == 0) return mrb_ary_new(mrb);
if (ARY_MAX_SIZE / times < a1->len) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "array size too big");
}
a2 = ary_new_capa(mrb, a1->len * times);
ptr = a2->ptr;
@@ -1031,7 +1031,7 @@ mrb_ary_join_m(mrb_state *mrb, mrb_value ary)
{
mrb_value sep = mrb_nil_value();
- mrb_get_args(mrb, "|S", &sep);
+ mrb_get_args(mrb, "|S!", &sep);
return mrb_ary_join(mrb, ary, sep);
}
diff --git a/src/class.c b/src/class.c
index e9cbc592d..33fb61211 100644
--- a/src/class.c
+++ b/src/class.c
@@ -435,12 +435,12 @@ to_sym(mrb_state *mrb, mrb_value ss)
----------------------------------------------------------------------------------------------
o: Object [mrb_value]
C: class/module [mrb_value]
- S: String [mrb_value]
- A: Array [mrb_value]
- H: Hash [mrb_value]
- s: String [char*,mrb_int] Receive two arguments.
- z: String [char*] NUL terminated string.
- a: Array [mrb_value*,mrb_int] Receive two arguments.
+ S: String [mrb_value] when ! follows, the value may be nil
+ A: Array [mrb_value] when ! follows, the value may be nil
+ H: Hash [mrb_value] when ! follows, the value may be nil
+ s: String [char*,mrb_int] Receive two arguments; s! gives (NULL,0) for nil
+ z: String [char*] NUL terminated string; z! gives NULL for nil
+ a: Array [mrb_value*,mrb_int] Receive two arguments; a! gives (NULL,0) for nil
f: Float [mrb_float]
i: Integer [mrb_int]
b: Boolean [mrb_bool]
@@ -525,6 +525,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_value *p;
p = va_arg(ap, mrb_value*);
+ if (*format == '!') {
+ format++;
+ if (i < argc && mrb_nil_p(*sp)) {
+ *p = *sp++;
+ i++;
+ break;
+ }
+ }
if (i < argc) {
*p = to_str(mrb, *sp++);
i++;
@@ -536,6 +544,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_value *p;
p = va_arg(ap, mrb_value*);
+ if (*format == '!') {
+ format++;
+ if (i < argc && mrb_nil_p(*sp)) {
+ *p = *sp++;
+ i++;
+ break;
+ }
+ }
if (i < argc) {
*p = to_ary(mrb, *sp++);
i++;
@@ -547,6 +563,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_value *p;
p = va_arg(ap, mrb_value*);
+ if (*format == '!') {
+ format++;
+ if (i < argc && mrb_nil_p(*sp)) {
+ *p = *sp++;
+ i++;
+ break;
+ }
+ }
if (i < argc) {
*p = to_hash(mrb, *sp++);
i++;
@@ -561,6 +585,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
ps = va_arg(ap, char**);
pl = va_arg(ap, mrb_int*);
+ if (*format == '!') {
+ format++;
+ if (i < argc && mrb_nil_p(*sp)) {
+ *ps = NULL;
+ *pl = 0;
+ i++;
+ break;
+ }
+ }
if (i < argc) {
ss = to_str(mrb, *sp++);
*ps = RSTRING_PTR(ss);
@@ -575,6 +608,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
const char **ps;
ps = va_arg(ap, const char**);
+ if (*format == '!') {
+ format++;
+ if (i < argc && mrb_nil_p(*sp)) {
+ *ps = NULL;
+ i++;
+ break;
+ }
+ }
if (i < argc) {
ss = to_str(mrb, *sp++);
*ps = mrb_string_value_cstr(mrb, &ss);
@@ -591,6 +632,15 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
pb = va_arg(ap, mrb_value**);
pl = va_arg(ap, mrb_int*);
+ if (*format == '!') {
+ format++;
+ if (i < argc && mrb_nil_p(*sp)) {
+ *pb = 0;
+ *pl = 0;
+ i++;
+ break;
+ }
+ }
if (i < argc) {
aa = to_ary(mrb, *sp++);
a = mrb_ary_ptr(aa);
@@ -676,6 +726,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
datap = va_arg(ap, void**);
type = va_arg(ap, struct mrb_data_type const*);
+ if (*format == '!') {
+ format++;
+ if (i < argc && mrb_nil_p(*sp)) {
+ *datap = 0;
+ i++;
+ break;
+ }
+ }
if (i < argc) {
*datap = mrb_data_get_ptr(mrb, *sp++, type);
++i;
@@ -1262,6 +1320,31 @@ mrb_bob_not(mrb_state *mrb, mrb_value cv)
return mrb_bool_value(!mrb_test(cv));
}
+void
+mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args)
+{
+ mrb_sym inspect;
+ mrb_value repr;
+
+ 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, self);
+ }
+ else if (mrb_respond_to(mrb, self, inspect) && mrb->c->ci - mrb->c->cibase < 64) {
+ repr = mrb_funcall_argv(mrb, self, inspect, 0, 0);
+ if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) {
+ repr = mrb_any_to_s(mrb, self);
+ }
+ }
+ else {
+ repr = mrb_any_to_s(mrb, self);
+ }
+
+ mrb_no_method_error(mrb, name, args, "undefined method '%S' for %S",
+ mrb_sym2str(mrb, name), repr);
+}
+
/* 15.3.1.3.30 */
/*
* call-seq:
@@ -1301,27 +1384,9 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod)
mrb_sym name;
mrb_value *a;
mrb_int alen;
- mrb_sym inspect;
- mrb_value repr;
mrb_get_args(mrb, "n*", &name, &a, &alen);
-
- 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) && mrb->c->ci - mrb->c->cibase < 64) {
- repr = mrb_funcall_argv(mrb, mod, inspect, 0, 0);
- if (mrb_string_p(repr) && RSTRING_LEN(repr) > 64) {
- repr = mrb_any_to_s(mrb, mod);
- }
- }
- else {
- repr = mrb_any_to_s(mrb, mod);
- }
-
- mrb_no_method_error(mrb, name, alen, a, "undefined method '%S' for %S", mrb_sym2str(mrb, name), repr);
+ mrb_method_missing(mrb, name, mod, mrb_ary_new_from_values(mrb, alen, a));
/* not reached */
return mrb_nil_value();
}
@@ -1543,10 +1608,10 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
case MRB_TT_CLASS:
case MRB_TT_MODULE:
case MRB_TT_SCLASS:
- mrb_str_append(mrb, str, mrb_inspect(mrb, v));
+ mrb_str_cat_str(mrb, str, mrb_inspect(mrb, v));
break;
default:
- mrb_str_append(mrb, str, mrb_any_to_s(mrb, v));
+ mrb_str_cat_str(mrb, str, mrb_any_to_s(mrb, v));
break;
}
return mrb_str_cat_lit(mrb, str, ">");
diff --git a/src/dump.c b/src/dump.c
index 2f2e5edcb..462e036b4 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -978,12 +978,8 @@ error_exit:
mrb_free(mrb, *bin);
*bin = NULL;
}
- if (lv_syms) {
- mrb_free(mrb, lv_syms);
- }
- if (filenames) {
- mrb_free(mrb, filenames);
- }
+ mrb_free(mrb, lv_syms);
+ mrb_free(mrb, filenames);
return result;
}
diff --git a/src/error.c b/src/error.c
index a800f77f9..359e5737b 100644
--- a/src/error.c
+++ b/src/error.c
@@ -152,7 +152,7 @@ exc_inspect(mrb_state *mrb, mrb_value exc)
mrb_str_append(mrb, str, line);
mrb_str_cat_lit(mrb, str, ": ");
if (append_mesg) {
- mrb_str_append(mrb, str, mesg);
+ mrb_str_cat_str(mrb, str, mesg);
mrb_str_cat_lit(mrb, str, " (");
}
mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, exc));
@@ -165,7 +165,7 @@ exc_inspect(mrb_state *mrb, mrb_value exc)
str = mrb_str_new_cstr(mrb, cname);
mrb_str_cat_lit(mrb, str, ": ");
if (append_mesg) {
- mrb_str_append(mrb, str, mesg);
+ mrb_str_cat_str(mrb, str, mesg);
}
else {
mrb_str_cat_cstr(mrb, str, cname);
@@ -424,15 +424,14 @@ mrb_sys_fail(mrb_state *mrb, const char *mesg)
}
MRB_API mrb_noreturn void
-mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_int argc, const mrb_value *argv, char const* fmt, ...)
+mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, char const* fmt, ...)
{
mrb_value exc;
va_list ap;
va_start(ap, fmt);
exc = mrb_funcall(mrb, mrb_obj_value(E_NOMETHOD_ERROR), "new", 3,
- mrb_vformat(mrb, fmt, ap), mrb_symbol_value(id),
- mrb_ary_new_from_values(mrb, argc, argv));
+ mrb_vformat(mrb, fmt, ap), mrb_symbol_value(id), args);
va_end(ap);
mrb_exc_raise(mrb, exc);
}
diff --git a/src/fmt_fp.c b/src/fmt_fp.c
index b467435a3..b27ebd6e9 100644
--- a/src/fmt_fp.c
+++ b/src/fmt_fp.c
@@ -90,7 +90,7 @@ fmt_u(uint32_t x, char *s)
typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)];
#endif
-#if ((defined(__CYGWIN32__) || defined(__NetBSD__) || defined(mips)) && !defined(__linux__)) || defined(__android__)
+#if ((defined(__CYGWIN__) || defined(__NetBSD__) || defined(mips)) && !defined(__linux__)) || defined(__android__)
#undef frexpl
#define frexpl frexp
#endif
diff --git a/src/range.c b/src/range.c
index b427dc1b7..b58b6a1c8 100644
--- a/src/range.c
+++ b/src/range.c
@@ -290,7 +290,7 @@ range_to_s(mrb_state *mrb, mrb_value range)
str2 = mrb_obj_as_string(mrb, r->edges->end);
str = mrb_str_dup(mrb, str);
mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2);
- mrb_str_append(mrb, str, str2);
+ mrb_str_cat_str(mrb, str, str2);
return str;
}
@@ -315,7 +315,7 @@ range_inspect(mrb_state *mrb, mrb_value range)
str2 = mrb_inspect(mrb, r->edges->end);
str = mrb_str_dup(mrb, str);
mrb_str_cat(mrb, str, "...", r->excl ? 3 : 2);
- mrb_str_append(mrb, str, str2);
+ mrb_str_cat_str(mrb, str, str2);
return str;
}
diff --git a/src/variable.c b/src/variable.c
index 1b2ad56a7..efe6fad12 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -609,7 +609,7 @@ inspect_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p)
else {
ins = mrb_inspect(mrb, v);
}
- mrb_str_append(mrb, str, ins);
+ mrb_str_cat_str(mrb, str, ins);
return 0;
}
diff --git a/src/vm.c b/src/vm.c
index 15a3926e3..22ea177e0 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -723,6 +723,8 @@ argnum_error(mrb_state *mrb, mrb_int num)
#define CALL_MAXARGS 127
+void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args);
+
MRB_API mrb_value
mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep)
{
@@ -1078,8 +1080,15 @@ RETRY_TRY_BLOCK:
m = mrb_method_search_vm(mrb, &c, missing);
if (!m) {
- mrb_no_method_error(mrb, mid, n, regs+a+1,
- "undefined method '%S' for %S", mrb_sym2str(mrb, mid), recv);
+ mrb_value args;
+
+ if (n == CALL_MAXARGS) {
+ args = regs[a+1];
+ }
+ else {
+ args = mrb_ary_new_from_values(mrb, n, regs+a+1);
+ }
+ mrb_method_missing(mrb, mid, recv, args);
}
mid = missing;
if (n == CALL_MAXARGS) {
diff --git a/tasks/mruby_build.rake b/tasks/mruby_build.rake
index 947b4ba77..9f8b4eda5 100644
--- a/tasks/mruby_build.rake
+++ b/tasks/mruby_build.rake
@@ -127,8 +127,8 @@ module MRuby
obj = objfile(cxx_src) if obj.nil?
file cxx_src => [src, __FILE__] do |t|
- File.open(t.name, 'w') do |f|
- f.write <<EOS
+ FileUtils.mkdir_p File.dirname t.name
+ IO.write t.name, <<EOS
#define __STDC_CONSTANT_MACROS
#define __STDC_LIMIT_MACROS
@@ -136,9 +136,8 @@ extern "C" {
#include "#{src}"
}
-#{File.basename(src) == 'error.c'? 'mrb_int mrb_jmpbuf::jmpbuf_id = 0;' : ''}
+#{src == "#{MRUBY_ROOT}/src/error.c"? 'mrb_int mrb_jmpbuf::jmpbuf_id = 0;' : ''}
EOS
- end
end
file obj => cxx_src do |t|