summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml2
-rw-r--r--include/mruby.h13
-rw-r--r--include/mruby/numeric.h1
-rw-r--r--mrbgems/mruby-array-ext/src/array.c12
-rw-r--r--mrbgems/mruby-kernel-ext/src/kernel.c3
-rw-r--r--src/class.c27
-rw-r--r--src/kernel.c2
-rw-r--r--src/numeric.c21
-rw-r--r--src/object.c19
-rw-r--r--src/proc.c6
-rw-r--r--src/string.c27
-rw-r--r--src/variable.c27
-rw-r--r--src/vm.c113
13 files changed, 123 insertions, 150 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index dbdd35fba..bf963ff0b 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -95,7 +95,7 @@ jobs:
Windows-Cygwin:
runs-on: windows-latest
- timeout-minutes: 10
+ timeout-minutes: 15
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
MRUBY_CONFIG: ci/gcc-clang
diff --git a/include/mruby.h b/include/mruby.h
index 21b96817a..806ceaff6 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -1269,7 +1269,10 @@ MRB_API mrb_bool mrb_obj_eq(mrb_state *mrb, mrb_value a, mrb_value b);
MRB_API mrb_bool mrb_obj_equal(mrb_state *mrb, mrb_value a, mrb_value b);
MRB_API mrb_bool mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2);
#ifndef MRB_NO_FLOAT
-MRB_API mrb_value mrb_to_float(mrb_state *mrb, mrb_value val);
+MRB_API mrb_value mrb_ensure_float_type(mrb_state *mrb, mrb_value val);
+#define mrb_as_float(mrb, x) mrb_float(mrb_ensure_float_type(mrb, x))
+/* obsolete: use mrb_ensure_float_type() instead */
+#define mrb_to_float(mrb, val) mrb_ensure_float_type(mrb, val)
#endif
MRB_API mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj);
MRB_API mrb_bool mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2);
@@ -1398,9 +1401,11 @@ MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str);
#define mrb_to_str(mrb, str) mrb_ensure_string_type(mrb,str)
/* obsolete: use mrb_obj_as_string() instead */
#define mrb_str_to_str(mrb, str) mrb_obj_as_string(mrb, str)
-MRB_API mrb_value mrb_to_integer(mrb_state *mrb, mrb_value val);
-#define mrb_to_int(mrb, val) mrb_to_integer(mrb, val)
-#define mrb_as_int(mrb, val) mrb_integer(mrb_to_integer(mrb, val))
+MRB_API mrb_value mrb_ensure_int_type(mrb_state *mrb, mrb_value val);
+#define mrb_as_int(mrb, val) mrb_integer(mrb_ensure_int_type(mrb, val))
+/* obsolete: use mrb_ensure_int_type() instead */
+#define mrb_to_integer(mrb, val) mrb_ensure_int_type(mrb, val)
+#define mrb_to_int(mrb, val) mrb_ensure_int_type(mrb, val)
/* string type checking (contrary to the name, it doesn't convert) */
MRB_API void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t);
diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h
index 4b14588ac..aec46413c 100644
--- a/include/mruby/numeric.h
+++ b/include/mruby/numeric.h
@@ -160,7 +160,6 @@ mrb_int_mul_overflow(mrb_int a, mrb_int b, mrb_int *c)
# endif /* MRB_USE_FLOAT32 */
MRB_API mrb_value mrb_float_to_integer(mrb_state *mrb, mrb_value val);
-MRB_API mrb_float mrb_as_float(mrb_state *mrb, mrb_value x);
/* internal functions */
mrb_float mrb_div_float(mrb_float x, mrb_float y);
diff --git a/mrbgems/mruby-array-ext/src/array.c b/mrbgems/mruby-array-ext/src/array.c
index d97778642..ae8a55d4d 100644
--- a/mrbgems/mruby-array-ext/src/array.c
+++ b/mrbgems/mruby-array-ext/src/array.c
@@ -264,12 +264,14 @@ mrb_ary_compact_bang(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_ary_rotate(mrb_state *mrb, mrb_value self)
{
+ mrb_int count=1;
+ mrb_get_args(mrb, "|i", &count);
+
mrb_value ary = mrb_ary_new(mrb);
mrb_int len = RARRAY_LEN(self);
mrb_value *p = RARRAY_PTR(self);
- mrb_int count=1, idx;
+ mrb_int idx;
- mrb_get_args(mrb, "|i", &count);
if (len <= 0) return ary;
if (count < 0) {
idx = len - (~count % len) - 1;
@@ -313,12 +315,14 @@ rev(mrb_value *p, mrb_int beg, mrb_int end)
static mrb_value
mrb_ary_rotate_bang(mrb_state *mrb, mrb_value self)
{
+ mrb_int count=1;
+ mrb_get_args(mrb, "|i", &count);
+
struct RArray *a = mrb_ary_ptr(self);
mrb_int len = ARY_LEN(a);
mrb_value *p = ARY_PTR(a);
- mrb_int count=1, idx;
+ mrb_int idx;
- mrb_get_args(mrb, "|i", &count);
mrb_ary_modify(mrb, a);
if (len == 0 || count == 0) return self;
if (count == 1) {
diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c
index 5b3dd6b35..976615f6e 100644
--- a/mrbgems/mruby-kernel-ext/src/kernel.c
+++ b/mrbgems/mruby-kernel-ext/src/kernel.c
@@ -187,6 +187,9 @@ mrb_f_float(mrb_state *mrb, mrb_value self)
{
mrb_value arg = mrb_get_arg1(mrb);
+ if (mrb_string_p(arg)) {
+ return mrb_float_value(mrb, mrb_str_to_dbl(mrb, arg, TRUE));
+ }
return mrb_to_float(mrb, arg);
}
#endif
diff --git a/src/class.c b/src/class.c
index 6249aa640..f97cc4c40 100644
--- a/src/class.c
+++ b/src/class.c
@@ -36,8 +36,8 @@ union mt_ptr {
/* method table structure */
typedef struct mt_tbl {
- size_t size;
- size_t alloc;
+ int size;
+ int alloc;
union mt_ptr *ptr;
} mt_tbl;
@@ -65,8 +65,8 @@ static void mt_put(mrb_state *mrb, mt_tbl *t, mrb_sym sym, mrb_sym flags, union
static void
mt_rehash(mrb_state *mrb, mt_tbl *t)
{
- size_t old_alloc = t->alloc;
- size_t new_alloc = old_alloc+8;
+ int old_alloc = t->alloc;
+ int new_alloc = old_alloc+8;
union mt_ptr *old_ptr = t->ptr;
khash_power2(new_alloc);
@@ -79,7 +79,7 @@ mt_rehash(mrb_state *mrb, mt_tbl *t)
mrb_sym *keys = (mrb_sym*)&old_ptr[old_alloc];
union mt_ptr *vals = old_ptr;
- for (size_t i = 0; i < old_alloc; i++) {
+ for (int i = 0; i < old_alloc; i++) {
mrb_sym key = keys[i];
if (MT_KEY_P(key)) {
mt_put(mrb, t, MT_KEY_SYM(key), MT_KEY_FLG(key), vals[i]);
@@ -94,8 +94,7 @@ mt_rehash(mrb_state *mrb, mt_tbl *t)
static void
mt_put(mrb_state *mrb, mt_tbl *t, mrb_sym sym, mrb_sym flags, union mt_ptr ptr)
{
- size_t hash, pos, start;
- ssize_t dpos = -1;
+ int hash, pos, start, dpos = -1;
if (t->alloc == 0) {
mt_rehash(mrb, t);
@@ -140,7 +139,7 @@ mt_put(mrb_state *mrb, mt_tbl *t, mrb_sym sym, mrb_sym flags, union mt_ptr ptr)
static mrb_sym
mt_get(mrb_state *mrb, mt_tbl *t, mrb_sym sym, union mt_ptr *pp)
{
- size_t hash, pos, start;
+ int hash, pos, start;
if (t == NULL) return 0;
if (t->alloc == 0) return 0;
@@ -150,7 +149,7 @@ mt_get(mrb_state *mrb, mt_tbl *t, mrb_sym sym, union mt_ptr *pp)
union mt_ptr *vals = t->ptr;
hash = kh_int_hash_func(mrb, sym);
#ifdef MRB_USE_INLINE_METHOD_CACHE
- size_t cpos = (hash^(uintptr_t)t) % MT_CACHE_SIZE;
+ int cpos = (hash^(uintptr_t)t) % MT_CACHE_SIZE;
pos = mt_cache[cpos];
if (cpos < t->alloc && t->table[cpos].key == sym) {
return &t->table[cpos];
@@ -182,7 +181,7 @@ mt_get(mrb_state *mrb, mt_tbl *t, mrb_sym sym, union mt_ptr *pp)
static mrb_bool
mt_del(mrb_state *mrb, mt_tbl *t, mrb_sym sym)
{
- size_t hash, pos, start;
+ int hash, pos, start;
if (t == NULL) return FALSE;
if (t->alloc == 0) return FALSE;
@@ -213,7 +212,7 @@ static struct mt_tbl*
mt_copy(mrb_state *mrb, mt_tbl *t)
{
mt_tbl *t2;
- size_t i;
+ int i;
if (t == NULL) return NULL;
if (t->alloc == 0) return NULL;
@@ -242,7 +241,7 @@ MRB_API void
mrb_mt_foreach(mrb_state *mrb, struct RClass *c, mrb_mt_foreach_func *fn, void *p)
{
mt_tbl *t = c->mt;
- size_t i;
+ int i;
if (t == NULL) return;
if (t->alloc == 0) return;
@@ -276,7 +275,7 @@ void
mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c)
{
mt_tbl *t = c->mt;
- size_t i;
+ int i;
if (t == NULL) return;
if (t->alloc == 0) return;
@@ -299,7 +298,7 @@ mrb_gc_mark_mt_size(mrb_state *mrb, struct RClass *c)
struct mt_tbl *h = c->mt;
if (!h) return 0;
- return h->size;
+ return (size_t)h->size;
}
void
diff --git a/src/kernel.c b/src/kernel.c
index 5ecebabeb..7a261560f 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -659,7 +659,7 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method(mrb, krn, "respond_to?", obj_respond_to, MRB_ARGS_ARG(1,1)); /* 15.3.1.3.43 */
mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */
mrb_define_method(mrb, krn, "__case_eqq", mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */
- mrb_define_method(mrb, krn, "__to_int", mrb_to_integer, MRB_ARGS_NONE()); /* internal */
+ mrb_define_method(mrb, krn, "__to_int", mrb_ensure_int_type, MRB_ARGS_NONE()); /* internal */
mrb_define_method(mrb, krn, "__ENCODING__", mrb_encoding, MRB_ARGS_NONE());
mrb_include_module(mrb, mrb->object_class, mrb->kernel_module);
diff --git a/src/numeric.c b/src/numeric.c
index fd9f5ce2c..fb3c0e48f 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -20,27 +20,6 @@
#endif
#endif
-#ifndef MRB_NO_FLOAT
-MRB_API mrb_float
-mrb_as_float(mrb_state *mrb, mrb_value val)
-{
- switch (mrb_type(val)) {
- case MRB_TT_INTEGER:
- return (mrb_float)mrb_integer(val);
- case MRB_TT_FLOAT:
- break;
- case MRB_TT_STRING:
- case MRB_TT_FALSE:
- case MRB_TT_TRUE:
- mrb_raise(mrb, E_TYPE_ERROR, "non float value");
- default:
- val = mrb_type_convert(mrb, val, MRB_TT_FLOAT, MRB_SYM(to_f));
- break;
- }
- return mrb_float(val);
-}
-#endif
-
static void
int_overflow(mrb_state *mrb, const char *reason)
{
diff --git a/src/object.c b/src/object.c
index de0298fab..8a2addc20 100644
--- a/src/object.c
+++ b/src/object.c
@@ -485,26 +485,22 @@ mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c)
}
MRB_API mrb_value
-mrb_to_integer(mrb_state *mrb, mrb_value val)
+mrb_ensure_int_type(mrb_state *mrb, mrb_value val)
{
-
if (!mrb_integer_p(val)) {
#ifndef MRB_NO_FLOAT
if (mrb_float_p(val)) {
return mrb_float_to_integer(mrb, val);
}
#endif
- if (mrb_string_p(val)) {
- mrb_raise(mrb, E_TYPE_ERROR, "can't convert String to Integer");
- }
- return mrb_type_convert(mrb, val, MRB_TT_INTEGER, MRB_SYM(to_i));
+ mrb_raisef(mrb, E_TYPE_ERROR, "%Y cannot be converted to Integer", val);
}
return val;
}
#ifndef MRB_NO_FLOAT
MRB_API mrb_value
-mrb_to_float(mrb_state *mrb, mrb_value val)
+mrb_ensure_float_type(mrb_state *mrb, mrb_value val)
{
if (mrb_nil_p(val)) {
mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Float");
@@ -516,11 +512,14 @@ mrb_to_float(mrb_state *mrb, mrb_value val)
case MRB_TT_FLOAT:
return val;
- case MRB_TT_STRING:
- return mrb_float_value(mrb, mrb_str_to_dbl(mrb, val, TRUE));
+ case MRB_TT_RATIONAL:
+ case MRB_TT_COMPLEX:
+ return mrb_type_convert(mrb, val, MRB_TT_FLOAT, MRB_SYM(to_f));
default:
- return mrb_type_convert(mrb, val, MRB_TT_FLOAT, MRB_SYM(to_f));
+ mrb_raisef(mrb, E_TYPE_ERROR, "%Y cannot be converted to Float", val);
+ /* not reached */
+ return val;
}
}
#endif
diff --git a/src/proc.c b/src/proc.c
index e11cb7fec..01a69fbf1 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -207,12 +207,12 @@ mrb_proc_copy(mrb_state *mrb, struct RProc *a, struct RProc *b)
/* already initialized proc */
return;
}
+ if (!MRB_PROC_CFUNC_P(b) && b->body.irep) {
+ mrb_irep_incref(mrb, (mrb_irep*)b->body.irep);
+ }
a->flags = b->flags;
a->body = b->body;
a->upper = b->upper;
- if (!MRB_PROC_CFUNC_P(a) && a->body.irep) {
- mrb_irep_incref(mrb, (mrb_irep*)a->body.irep);
- }
a->e.env = b->e.env;
/* a->e.target_class = a->e.target_class; */
}
diff --git a/src/string.c b/src/string.c
index 6c9dd2996..332c4e777 100644
--- a/src/string.c
+++ b/src/string.c
@@ -1108,6 +1108,9 @@ str_convert_range(mrb_state *mrb, mrb_value str, mrb_value indx, mrb_value alen,
}
else {
switch (mrb_type(indx)) {
+ default:
+ indx = mrb_ensure_int_type(mrb, indx);
+ /* fall through */
case MRB_TT_INTEGER:
*beg = mrb_integer(indx);
*len = 1;
@@ -1120,16 +1123,6 @@ str_convert_range(mrb_state *mrb, mrb_value str, mrb_value indx, mrb_value alen,
return STR_BYTE_RANGE_CORRECTED;
case MRB_TT_RANGE:
- goto range_arg;
-
- default:
- indx = mrb_to_integer(mrb, indx);
- if (mrb_integer_p(indx)) {
- *beg = mrb_integer(indx);
- *len = 1;
- return STR_CHAR_RANGE;
- }
-range_arg:
*len = RSTRING_CHAR_LEN(str);
switch (mrb_range_beg_len(mrb, indx, beg, len, *len, TRUE)) {
case MRB_RANGE_OK:
@@ -1139,8 +1132,6 @@ range_arg:
default:
break;
}
-
- mrb_raise(mrb, E_TYPE_ERROR, "can't convert to Integer");
}
}
return STR_OUT_OF_RANGE;
@@ -2047,9 +2038,11 @@ static mrb_value
mrb_str_rindex(mrb_state *mrb, mrb_value str)
{
mrb_value sub;
- mrb_int pos, len = RSTRING_CHAR_LEN(str);
+ mrb_int pos;
+ int argc = mrb_get_args(mrb, "S|i", &sub, &pos);
+ mrb_int len = RSTRING_CHAR_LEN(str);
- if (mrb_get_args(mrb, "S|i", &sub, &pos) == 1) {
+ if (argc == 1) {
pos = len;
}
else {
@@ -2828,23 +2821,25 @@ static mrb_value
mrb_str_byteslice(mrb_state *mrb, mrb_value str)
{
mrb_value a1;
- mrb_int str_len = RSTRING_LEN(str), beg, len;
+ mrb_int str_len, beg, len;
mrb_bool empty = TRUE;
len = mrb_get_argc(mrb);
switch (len) {
case 2:
mrb_get_args(mrb, "ii", &beg, &len);
+ str_len = RSTRING_LEN(str);
break;
case 1:
a1 = mrb_get_arg1(mrb);
+ str_len = RSTRING_LEN(str);
if (mrb_range_p(a1)) {
if (mrb_range_beg_len(mrb, a1, &beg, &len, str_len, TRUE) != MRB_RANGE_OK) {
return mrb_nil_value();
}
}
else {
- beg = mrb_integer(mrb_to_integer(mrb, a1));
+ beg = mrb_as_int(mrb, a1);
len = 1;
empty = FALSE;
}
diff --git a/src/variable.c b/src/variable.c
index daee93655..53b760d0f 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -14,7 +14,7 @@
/* Instance variable table structure */
typedef struct iv_tbl {
- size_t size, alloc;
+ int size, alloc;
mrb_value *ptr;
} iv_tbl;
@@ -41,8 +41,8 @@ static void iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val);
static void
iv_rehash(mrb_state *mrb, iv_tbl *t)
{
- size_t old_alloc = t->alloc;
- size_t new_alloc = old_alloc+4;
+ int old_alloc = t->alloc;
+ int new_alloc = old_alloc+4;
mrb_value *old_ptr = t->ptr;
khash_power2(new_alloc);
@@ -55,7 +55,7 @@ iv_rehash(mrb_state *mrb, iv_tbl *t)
mrb_sym *keys = (mrb_sym*)&old_ptr[old_alloc];
mrb_value *vals = old_ptr;
- for (size_t i = 0; i < old_alloc; i++) {
+ for (int i = 0; i < old_alloc; i++) {
if (IV_KEY_P(keys[i])) {
iv_put(mrb, t, keys[i], vals[i]);
}
@@ -67,8 +67,7 @@ iv_rehash(mrb_state *mrb, iv_tbl *t)
static void
iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
{
- size_t hash, pos, start;
- int dpos = -1;
+ int hash, pos, start, dpos = -1;
if (t == NULL) return;
if (t->alloc == 0) {
@@ -112,10 +111,10 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
}
/* Get a value for a symbol from the instance variable table. */
-static size_t
+static int
iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
{
- size_t hash, pos, start;
+ int hash, pos, start;
if (t == NULL) return FALSE;
if (t->alloc == 0) return FALSE;
@@ -145,7 +144,7 @@ iv_get(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
static mrb_bool
iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
{
- size_t hash, pos, start;
+ int hash, pos, start;
if (t == NULL) return FALSE;
if (t->alloc == 0) return FALSE;
@@ -177,7 +176,7 @@ iv_del(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value *vp)
static void
iv_foreach(mrb_state *mrb, iv_tbl *t, mrb_iv_foreach_func *func, void *p)
{
- size_t i;
+ int i;
if (t == NULL) return;
if (t->alloc == 0) return;
@@ -201,7 +200,7 @@ static size_t
iv_size(mrb_state *mrb, iv_tbl *t)
{
if (t == NULL) return 0;
- return t->size;
+ return (size_t)t->size;
}
/* Copy the instance variable table. */
@@ -209,7 +208,7 @@ static iv_tbl*
iv_copy(mrb_state *mrb, iv_tbl *t)
{
iv_tbl *t2;
- size_t i;
+ int i;
if (t == NULL) return NULL;
if (t->alloc == 0) return NULL;
@@ -486,7 +485,7 @@ mrb_value
mrb_obj_iv_inspect(mrb_state *mrb, struct RObject *obj)
{
iv_tbl *t = obj->iv;
- size_t len = iv_size(mrb, t);
+ int len = iv_size(mrb, t);
if (len > 0) {
const char *cn = mrb_obj_classname(mrb, mrb_obj_value(obj));
@@ -660,7 +659,7 @@ mrb_mod_cv_set(mrb_state *mrb, struct RClass *c, mrb_sym sym, mrb_value v)
while (c) {
iv_tbl *t = c->iv;
- size_t pos = iv_get(mrb, t, sym, NULL);
+ int pos = iv_get(mrb, t, sym, NULL);
if (pos) {
mrb_check_frozen(mrb, c);
diff --git a/src/vm.c b/src/vm.c
index 1a411b534..0d197098d 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -430,6 +430,52 @@ mrb_ci_nregs(mrb_callinfo *ci)
return nregs;
}
+mrb_value mrb_obj_missing(mrb_state *mrb, mrb_value mod);
+
+static mrb_method_t
+prepare_missing(mrb_state *mrb, mrb_value recv, mrb_sym mid, struct RClass **clsp, uint32_t a, uint16_t *c, mrb_value blk, int super)
+{
+ mrb_sym missing = MRB_SYM(method_missing);
+ mrb_callinfo *ci = mrb->c->ci;
+ uint16_t b = *c;
+ mrb_int n = b & 0xf;
+ mrb_int nk = (b>>4) & 0xf;
+ mrb_value *argv = &ci->stack[a+1];
+ mrb_value args;
+ mrb_method_t m;
+
+ /* pack positional arguments */
+ if (n == 15) args = argv[0];
+ else args = mrb_ary_new_from_values(mrb, n, argv);
+
+ if (mrb_func_basic_p(mrb, recv, missing, mrb_obj_missing)) {
+ method_missing:
+ if (super) mrb_no_method_error(mrb, mid, args, "no superclass method '%n'", mid);
+ else mrb_method_missing(mrb, mid, recv, args);
+ /* not reached */
+ }
+ if (mid != missing) {
+ *clsp = mrb_class(mrb, recv);
+ }
+ m = mrb_method_search_vm(mrb, clsp, missing);
+ if (MRB_METHOD_UNDEF_P(m)) goto method_missing; /* just in case */
+ mrb_stack_extend(mrb, a+4);
+
+ argv = &ci->stack[a+1]; /* maybe reallocated */
+ argv[0] = args;
+ if (nk == 0) {
+ argv[1] = blk;
+ }
+ else {
+ mrb_assert(nk == 15);
+ argv[1] = argv[n];
+ argv[2] = blk;
+ }
+ *c = 15 | (nk<<4);
+ mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));
+ return m;
+}
+
MRB_API mrb_value
mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv, mrb_value blk)
{
@@ -478,24 +524,15 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
c = mrb_class(mrb, self);
m = mrb_method_search_vm(mrb, &c, mid);
mrb_stack_extend(mrb, n + argc + 3);
- if (MRB_METHOD_UNDEF_P(m) || argc >= 15) {
- mrb_value args = mrb_ary_new_from_values(mrb, argc, argv);
-
- ci->stack[n+1] = args;
+ if (argc >= 15) {
+ ci->stack[n+1] = mrb_ary_new_from_values(mrb, argc, argv);
argc = 15;
}
if (MRB_METHOD_UNDEF_P(m)) {
- mrb_sym missing = MRB_SYM(method_missing);
- mrb_value args = ci->stack[n+1];
-
- m = mrb_method_search_vm(mrb, &c, missing);
- if (MRB_METHOD_UNDEF_P(m)) {
- mrb_method_missing(mrb, mid, self, args);
- }
- mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));
- mrb_stack_extend(mrb, n+2);
- ci->stack[n+1] = args;
- argc = 15;
+ uint16_t ac = (uint16_t)argc;
+ m = prepare_missing(mrb, self, mid, &c, n, &ac, mrb_nil_value(), 0);
+ argc = (mrb_int)ac;
+ mid = MRB_SYM(method_missing);
}
ci = cipush(mrb, n, 0, c, NULL, mid, argc);
if (MRB_METHOD_PROC_P(m)) {
@@ -1123,52 +1160,6 @@ hash_new_from_values(mrb_state *mrb, mrb_int argc, mrb_value *regs)
return hash;
}
-mrb_value mrb_obj_missing(mrb_state *mrb, mrb_value mod);
-
-static mrb_method_t
-prepare_missing(mrb_state *mrb, mrb_value recv, mrb_sym mid, struct RClass **clsp, uint32_t a, uint16_t *c, mrb_value blk, int super)
-{
- mrb_sym missing = MRB_SYM(method_missing);
- mrb_callinfo *ci = mrb->c->ci;
- uint16_t b = *c;
- mrb_int n = b & 0xf;
- mrb_int nk = (b>>4) & 0xf;
- mrb_value *argv = &ci->stack[a+1];
- mrb_value args;
- mrb_method_t m;
-
- /* pack positional arguments */
- if (n == 15) args = argv[0];
- else args = mrb_ary_new_from_values(mrb, n, argv);
-
- if (mrb_func_basic_p(mrb, recv, missing, mrb_obj_missing)) {
- method_missing:
- if (super) mrb_no_method_error(mrb, mid, args, "no superclass method '%n'", mid);
- else mrb_method_missing(mrb, mid, recv, args);
- /* not reached */
- }
- if (mid != missing) {
- *clsp = mrb_class(mrb, recv);
- }
- m = mrb_method_search_vm(mrb, clsp, missing);
- if (MRB_METHOD_UNDEF_P(m)) goto method_missing; /* just in case */
- mrb_stack_extend(mrb, a+4);
-
- argv = &ci->stack[a+1]; /* maybe reallocated */
- argv[0] = args;
- if (nk == 0) {
- argv[1] = blk;
- }
- else {
- mrb_assert(nk == 15);
- argv[1] = argv[n];
- argv[2] = blk;
- }
- *c = 15 | (nk<<4);
- mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));
- return m;
-}
-
void mrb_method_added(mrb_state *mrb, struct RClass *c, mrb_sym mid);
mrb_value mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value idx, mrb_value len);