summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/array.c7
-rw-r--r--src/class.c119
-rw-r--r--src/dump.c10
-rw-r--r--src/error.c9
-rw-r--r--src/etc.c10
-rw-r--r--src/fmt_fp.c2
-rw-r--r--src/load.c2
-rw-r--r--src/numeric.c15
-rw-r--r--src/range.c4
-rw-r--r--src/string.c33
-rw-r--r--src/variable.c2
-rw-r--r--src/version.c1
-rw-r--r--src/vm.c22
13 files changed, 164 insertions, 72 deletions
diff --git a/src/array.c b/src/array.c
index f48719310..2622ee528 100644
--- a/src/array.c
+++ b/src/array.c
@@ -19,7 +19,6 @@
static inline mrb_value
ary_elt(mrb_value ary, mrb_int offset)
{
- if (RARRAY_LEN(ary) == 0) return mrb_nil_value();
if (offset < 0 || RARRAY_LEN(ary) <= offset) {
return mrb_nil_value();
}
@@ -295,7 +294,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 +348,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 +1030,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..734f38043 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -16,7 +16,7 @@
#define FLAG_BYTEORDER_NONATIVE 0
#ifdef MRB_USE_FLOAT
-#define MRB_FLOAT_FMT "%.9e"
+#define MRB_FLOAT_FMT "%.8e"
#else
#define MRB_FLOAT_FMT "%.16e"
#endif
@@ -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/etc.c b/src/etc.c
index a8a21e740..f5a502795 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -67,17 +67,15 @@ mrb_data_get_ptr(mrb_state *mrb, mrb_value obj, const mrb_data_type *type)
MRB_API mrb_sym
mrb_obj_to_sym(mrb_state *mrb, mrb_value name)
{
- mrb_value tmp;
mrb_sym id;
switch (mrb_type(name)) {
default:
- tmp = mrb_check_string_type(mrb, name);
- if (mrb_nil_p(tmp)) {
- tmp = mrb_inspect(mrb, name);
- mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp);
+ name = mrb_check_string_type(mrb, name);
+ if (mrb_nil_p(name)) {
+ name = mrb_inspect(mrb, name);
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", name);
}
- name = tmp;
/* fall through */
case MRB_TT_STRING:
name = mrb_str_intern(mrb, name);
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/load.c b/src/load.c
index a9f1641bf..36fae9aee 100644
--- a/src/load.c
+++ b/src/load.c
@@ -529,7 +529,7 @@ read_binary_header(const uint8_t *bin, size_t *bin_size, uint16_t *crc, uint8_t
else if (memcmp(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident)) == 0) {
if (bigendian_p())
*flags |= FLAG_BYTEORDER_LIL;
- else
+ else
*flags |= FLAG_BYTEORDER_NATIVE;
}
else {
diff --git a/src/numeric.c b/src/numeric.c
index b9aef51d9..1a3c903f0 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -55,7 +55,8 @@ num_pow(mrb_state *mrb, mrb_value x)
mrb_get_args(mrb, "o", &y);
yv = mrb_to_flo(mrb, y);
d = pow(mrb_to_flo(mrb, x), yv);
- if (mrb_fixnum_p(x) && mrb_fixnum_p(y) && FIXABLE(d) && yv > 0)
+ if (mrb_fixnum_p(x) && mrb_fixnum_p(y) && FIXABLE(d) && yv > 0 &&
+ (d < 0 || (d > 0 && (mrb_int)d > 0)))
return mrb_fixnum_value((mrb_int)d);
return mrb_float_value(mrb, d);
}
@@ -819,11 +820,13 @@ fix_xor(mrb_state *mrb, mrb_value x)
static mrb_value
lshift(mrb_state *mrb, mrb_int val, mrb_int width)
{
- mrb_assert(width >= 0);
+ mrb_assert(width > 0);
if (width > NUMERIC_SHIFT_WIDTH_MAX) {
- mrb_raisef(mrb, E_RANGE_ERROR, "width(%S) > (%S:MRB_INT_BIT-1)",
- mrb_fixnum_value(width),
- mrb_fixnum_value(NUMERIC_SHIFT_WIDTH_MAX));
+ mrb_float f = (mrb_float)val;
+ while (width--) {
+ f *= 2;
+ }
+ return mrb_float_value(mrb, f);
}
return mrb_fixnum_value(val << width);
}
@@ -831,7 +834,7 @@ lshift(mrb_state *mrb, mrb_int val, mrb_int width)
static mrb_value
rshift(mrb_int val, mrb_int width)
{
- mrb_assert(width >= 0);
+ mrb_assert(width > 0);
if (width >= NUMERIC_SHIFT_WIDTH_MAX) {
if (val < 0) {
return mrb_fixnum_value(-1);
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/string.c b/src/string.c
index 45ba38c9d..08caf3bae 100644
--- a/src/string.c
+++ b/src/string.c
@@ -75,9 +75,18 @@ str_decref(mrb_state *mrb, mrb_shared_string *shared)
}
}
+static void
+check_frozen(mrb_state *mrb, struct RString *s)
+{
+ if (RSTR_FROZEN_P(s)) {
+ mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen string");
+ }
+}
+
MRB_API void
mrb_str_modify(mrb_state *mrb, struct RString *s)
{
+ check_frozen(mrb, s);
if (RSTR_SHARED_P(s)) {
mrb_shared_string *shared = s->as.heap.aux.shared;
@@ -119,6 +128,15 @@ mrb_str_modify(mrb_state *mrb, struct RString *s)
}
}
+static mrb_value
+mrb_str_freeze(mrb_state *mrb, mrb_value str)
+{
+ struct RString *s = mrb_str_ptr(str);
+
+ RSTR_SET_FROZEN_FLAG(s);
+ return str;
+}
+
MRB_API mrb_value
mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len)
{
@@ -1345,6 +1363,7 @@ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
{
long len;
+ check_frozen(mrb, s1);
len = RSTR_LEN(s2);
if (RSTR_SHARED_P(s1)) {
str_decref(mrb, s1->as.heap.aux.shared);
@@ -1844,7 +1863,7 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
const char *p;
char sign = 1;
int c, uscore;
- unsigned long n = 0;
+ uint64_t n = 0;
mrb_int val;
#define conv_digit(c) \
@@ -1964,9 +1983,9 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck)
}
n *= base;
n += c;
- }
- if (n > MRB_INT_MAX) {
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer", mrb_str_new_cstr(mrb, str));
+ if (n > MRB_INT_MAX) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer", mrb_str_new_cstr(mrb, str));
+ }
}
val = n;
if (badcheck) {
@@ -2366,10 +2385,10 @@ mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2)
}
MRB_API mrb_value
-mrb_str_append(mrb_state *mrb, mrb_value str, mrb_value str2)
+mrb_str_append(mrb_state *mrb, mrb_value str1, mrb_value str2)
{
str2 = mrb_str_to_str(mrb, str2);
- return mrb_str_cat_str(mrb, str, str2);
+ return mrb_str_cat_str(mrb, str1, str2);
}
#define CHAR_ESC_LEN 13 /* sizeof(\x{ hex of 32bit unsigned int } \0) */
@@ -2514,4 +2533,6 @@ mrb_init_string(mrb_state *mrb)
mrb_define_method(mrb, s, "upcase!", mrb_str_upcase_bang, MRB_ARGS_NONE()); /* 15.2.10.5.43 */
mrb_define_method(mrb, s, "inspect", mrb_str_inspect, MRB_ARGS_NONE()); /* 15.2.10.5.46(x) */
mrb_define_method(mrb, s, "bytes", mrb_str_bytes, MRB_ARGS_NONE());
+
+ mrb_define_method(mrb, s, "freeze", mrb_str_freeze, MRB_ARGS_NONE());
}
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/version.c b/src/version.c
index 7aac44d62..fc3b2fc7a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -7,6 +7,7 @@ mrb_init_version(mrb_state* mrb)
mrb_define_global_const(mrb, "RUBY_VERSION", mrb_str_new_lit(mrb, MRUBY_RUBY_VERSION));
mrb_define_global_const(mrb, "RUBY_ENGINE", mrb_str_new_lit(mrb, MRUBY_RUBY_ENGINE));
mrb_define_global_const(mrb, "MRUBY_VERSION", mrb_str_new_lit(mrb, MRUBY_VERSION));
+ mrb_define_global_const(mrb, "MRUBY_RELEASE_NO", mrb_fixnum_value(MRUBY_RELEASE_NO));
mrb_define_global_const(mrb, "MRUBY_RELEASE_DATE", mrb_str_new_lit(mrb, MRUBY_RELEASE_DATE));
mrb_define_global_const(mrb, "MRUBY_DESCRIPTION", mrb_str_new_lit(mrb, MRUBY_DESCRIPTION));
mrb_define_global_const(mrb, "MRUBY_COPYRIGHT", mrb_str_new_lit(mrb, MRUBY_COPYRIGHT));
diff --git a/src/vm.c b/src/vm.c
index 15a3926e3..8419931d0 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -266,6 +266,7 @@ ecall(mrb_state *mrb, int i)
mrb_value *self = mrb->c->stack;
struct RObject *exc;
+ if (i<0) return;
p = mrb->c->ensure[i];
if (!p) return;
if (mrb->c->ci->eidx > i)
@@ -723,6 +724,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)
{
@@ -1030,7 +1033,7 @@ RETRY_TRY_BLOCK:
mrb_callinfo *ci = mrb->c->ci;
int n, eidx = ci->eidx;
- for (n=0; n<a && eidx > ci[-1].eidx; n++) {
+ for (n=0; n<a && (ci == mrb->c->cibase || eidx > ci[-1].eidx); n++) {
ecall(mrb, --eidx);
ARENA_RESTORE(mrb, ai);
}
@@ -1078,8 +1081,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) {
@@ -1476,9 +1486,6 @@ RETRY_TRY_BLOCK:
if (ci->ridx == 0) goto L_STOP;
goto L_RESCUE;
}
- while (eidx > ci[-1].eidx) {
- ecall(mrb, --eidx);
- }
while (ci[0].ridx == ci[-1].ridx) {
cipop(mrb);
ci = mrb->c->ci;
@@ -1488,6 +1495,9 @@ RETRY_TRY_BLOCK:
MRB_THROW(prev_jmp);
}
if (ci == mrb->c->cibase) {
+ while (eidx > 0) {
+ ecall(mrb, --eidx);
+ }
if (ci->ridx == 0) {
if (mrb->c == mrb->root_c) {
regs = mrb->c->stack = mrb->c->stbase;