summaryrefslogtreecommitdiffhomepage
path: root/src/class.c
diff options
context:
space:
mode:
authorHiroshi Mimaki <[email protected]>2019-10-18 14:46:03 +0900
committerHiroshi Mimaki <[email protected]>2019-10-18 14:46:03 +0900
commitb6546835457d1935a9c77965686b2a1256874d96 (patch)
tree724cfd71a7c956b0648e8c58f3717d797fff5f29 /src/class.c
parent8ee516436b8d174a50764939bee23a442aa00b3f (diff)
parent20d01f118ddb7e7f2f36926a7a3db35573611857 (diff)
downloadmruby-b6546835457d1935a9c77965686b2a1256874d96.tar.gz
mruby-b6546835457d1935a9c77965686b2a1256874d96.zip
Merge master.
Diffstat (limited to 'src/class.c')
-rw-r--r--src/class.c654
1 files changed, 374 insertions, 280 deletions
diff --git a/src/class.c b/src/class.c
index 5c5ee9d17..b1c7513de 100644
--- a/src/class.c
+++ b/src/class.c
@@ -7,6 +7,7 @@
#include <stdarg.h>
#include <mruby.h>
#include <mruby/array.h>
+#include <mruby/hash.h>
#include <mruby/class.h>
#include <mruby/numeric.h>
#include <mruby/proc.h>
@@ -15,6 +16,7 @@
#include <mruby/error.h>
#include <mruby/data.h>
#include <mruby/istruct.h>
+#include <mruby/opcode.h>
KHASH_DEFINE(mt, mrb_sym, mrb_method_t, TRUE, kh_int_hash_func, kh_int_hash_equal)
@@ -63,18 +65,31 @@ mrb_class_name_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb
name = mrb_symbol_value(id);
}
else {
- name = mrb_class_path(mrb, outer);
- if (mrb_nil_p(name)) { /* unnamed outer class */
+ const char *n;
+ mrb_int len;
+ mrb_value outer_name = mrb_class_path(mrb, outer);
+
+ if (mrb_nil_p(outer_name)) { /* unnamed outer class */
if (outer != mrb->object_class && outer != c) {
- mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"),
- mrb_obj_value(outer));
+ mrb_obj_iv_set_force(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"),
+ mrb_obj_value(outer));
}
return;
}
- mrb_str_cat_cstr(mrb, name, "::");
- mrb_str_cat_cstr(mrb, name, mrb_sym2name(mrb, id));
+ n = mrb_sym_name_len(mrb, id, &len);
+ name = mrb_str_new_capa(mrb, RSTRING_LEN(outer_name) + 2 + len);
+ mrb_str_cat_str(mrb, name, outer_name);
+ mrb_str_cat_lit(mrb, name, "::");
+ mrb_str_cat(mrb, name, n, len);
+ MRB_SET_FROZEN_FLAG(mrb_obj_ptr(name));
}
- mrb_obj_iv_set(mrb, (struct RObject*)c, nsym, name);
+ mrb_obj_iv_set_force(mrb, (struct RObject*)c, nsym, name);
+}
+
+mrb_bool
+mrb_const_name_p(mrb_state *mrb, const char *name, mrb_int len)
+{
+ return len > 0 && ISUPPER(name[0]) && mrb_ident_p(name+1, len-1);
}
static void
@@ -120,6 +135,7 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o)
mrb_field_write_barrier(mrb, (struct RBasic*)o, (struct RBasic*)sc);
mrb_field_write_barrier(mrb, (struct RBasic*)sc, (struct RBasic*)o);
mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern_lit(mrb, "__attached__"), mrb_obj_value(o));
+ sc->flags |= o->flags & MRB_FL_OBJ_IS_FROZEN;
}
static mrb_value
@@ -170,7 +186,7 @@ static void
check_if_class_or_module(mrb_state *mrb, mrb_value obj)
{
if (!class_ptr_p(obj)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", mrb_inspect(mrb, obj));
+ mrb_raisef(mrb, E_TYPE_ERROR, "%!v is not a class/module", obj);
}
}
@@ -200,15 +216,15 @@ mrb_define_module(mrb_state *mrb, const char *name)
return define_module(mrb, mrb_intern_cstr(mrb, name), mrb->object_class);
}
-MRB_API struct RClass*
+struct RClass*
mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id)
{
check_if_class_or_module(mrb, outer);
if (mrb_const_defined_at(mrb, outer, id)) {
mrb_value old = mrb_const_get(mrb, outer, id);
- if (mrb_type(old) != MRB_TT_MODULE) {
- mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a module", mrb_inspect(mrb, old));
+ if (!mrb_module_p(old)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "%!v is not a module", old);
}
return mrb_class_ptr(old);
}
@@ -241,9 +257,8 @@ define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass *
c = class_from_sym(mrb, outer, name);
MRB_CLASS_ORIGIN(c);
if (super && mrb_class_real(c->super) != super) {
- mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %S (%S not %S)",
- mrb_sym2str(mrb, name),
- mrb_obj_value(c->super), mrb_obj_value(super));
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for Class %n (%C not %C)",
+ name, c->super, super);
}
return c;
}
@@ -258,7 +273,7 @@ MRB_API struct RClass*
mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super)
{
if (!super) {
- mrb_warn(mrb, "no super class for '%S', Object assumed", mrb_sym2str(mrb, name));
+ mrb_warn(mrb, "no super class for '%n', Object assumed", name);
}
return define_class(mrb, name, super, mrb->object_class);
}
@@ -298,16 +313,15 @@ mrb_class_inherited(mrb_state *mrb, struct RClass *super, struct RClass *klass)
}
}
-MRB_API struct RClass*
+struct RClass*
mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id)
{
struct RClass *s;
struct RClass *c;
if (!mrb_nil_p(super)) {
- if (mrb_type(super) != MRB_TT_CLASS) {
- mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)",
- mrb_inspect(mrb, super));
+ if (!mrb_class_p(super)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%!v given)", super);
}
s = mrb_class_ptr(super);
}
@@ -318,14 +332,14 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id
if (mrb_const_defined_at(mrb, outer, id)) {
mrb_value old = mrb_const_get(mrb, outer, id);
- if (mrb_type(old) != MRB_TT_CLASS) {
- mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class", mrb_inspect(mrb, old));
+ if (!mrb_class_p(old)) {
+ mrb_raisef(mrb, E_TYPE_ERROR, "%!v is not a class", old);
}
c = mrb_class_ptr(old);
if (s) {
/* check super class */
if (mrb_class_real(c->super) != s) {
- mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %S", old);
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %v", old);
}
}
return c;
@@ -375,7 +389,7 @@ mrb_exc_get(mrb_state *mrb, const char *name)
mrb_value c = mrb_const_get(mrb, mrb_obj_value(mrb->object_class),
mrb_intern_cstr(mrb, name));
- if (mrb_type(c) != MRB_TT_CLASS) {
+ if (!mrb_class_p(c)) {
mrb_raise(mrb, mrb->eException_class, "exception corrupted");
}
exc = e = mrb_class_ptr(c);
@@ -403,7 +417,7 @@ mrb_module_get(mrb_state *mrb, const char *name)
/*!
* Defines a class under the namespace of \a outer.
* \param outer a class which contains the new class.
- * \param id name of the new class
+ * \param name name of the new class
* \param super a class from which the new class will derive.
* NULL means \c Object class.
* \return the created class
@@ -424,8 +438,7 @@ mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, s
#if 0
if (!super) {
- mrb_warn(mrb, "no super class for '%S::%S', Object assumed",
- mrb_obj_value(outer), mrb_sym2str(mrb, id));
+ mrb_warn(mrb, "no super class for '%C::%n', Object assumed", outer, id);
}
#endif
c = define_class(mrb, id, super, outer);
@@ -441,12 +454,7 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_method_
MRB_CLASS_ORIGIN(c);
h = c->mt;
- if (MRB_FROZEN_P(c)) {
- if (c->tt == MRB_TT_MODULE)
- mrb_raise(mrb, E_FROZEN_ERROR, "can't modify frozen module");
- else
- mrb_raise(mrb, E_FROZEN_ERROR, "can't modify frozen class");
- }
+ mrb_check_frozen(mrb, c);
if (!h) h = c->mt = kh_init(mt, mrb);
k = kh_put(mt, mrb, h, mid);
kh_value(h, k) = m;
@@ -470,6 +478,9 @@ mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t f
int ai = mrb_gc_arena_save(mrb);
MRB_METHOD_FROM_FUNC(m, func);
+ if (aspec == MRB_ARGS_NONE()) {
+ MRB_METHOD_NOARG_SET(m);
+ }
mrb_define_method_raw(mrb, c, mid, m);
mrb_gc_arena_restore(mrb, ai);
}
@@ -487,8 +498,7 @@ mrb_notimplement(mrb_state *mrb)
mrb_callinfo *ci = mrb->c->ci;
if (ci->mid) {
- mrb_value str = mrb_sym2str(mrb, ci->mid);
- mrb_raisef(mrb, E_NOTIMP_ERROR, "%S() function is unimplemented on this machine", str);
+ mrb_raisef(mrb, E_NOTIMP_ERROR, "%n() function is unimplemented on this machine", ci->mid);
}
}
@@ -501,30 +511,17 @@ mrb_notimplement_m(mrb_state *mrb, mrb_value self)
return mrb_nil_value();
}
-#define CHECK_TYPE(mrb, val, t, c) do { \
- if (mrb_type(val) != (t)) {\
- mrb_raisef(mrb, E_TYPE_ERROR, "expected %S", mrb_str_new_lit(mrb, c));\
- }\
-} while (0)
-
-static mrb_value
-to_str(mrb_state *mrb, mrb_value val)
-{
- CHECK_TYPE(mrb, val, MRB_TT_STRING, "String");
- return val;
-}
-
static mrb_value
to_ary(mrb_state *mrb, mrb_value val)
{
- CHECK_TYPE(mrb, val, MRB_TT_ARRAY, "Array");
+ mrb_check_type(mrb, val, MRB_TT_ARRAY);
return val;
}
static mrb_value
to_hash(mrb_state *mrb, mrb_value val)
{
- CHECK_TYPE(mrb, val, MRB_TT_HASH, "Hash");
+ mrb_check_type(mrb, val, MRB_TT_HASH);
return val;
}
@@ -559,6 +556,8 @@ mrb_get_argv(mrb_state *mrb)
return array_argv;
}
+void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self);
+
/*
retrieve arguments from mrb_state.
@@ -571,23 +570,24 @@ mrb_get_argv(mrb_state *mrb)
string mruby type C type note
----------------------------------------------------------------------------------------------
o: Object [mrb_value]
- C: class/module [mrb_value]
+ C: Class/Module [mrb_value]
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]
- n: Symbol [mrb_sym]
- d: Data [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified
- I: Inline struct [void*]
- &: Block [mrb_value] &! raises exception if no block given
+ f: Fixnum/Float [mrb_float]
+ i: Fixnum/Float [mrb_int]
+ b: boolean [mrb_bool]
+ n: String/Symbol [mrb_sym]
+ d: data [void*,mrb_data_type const] 2nd argument will be used to check data type so it won't be modified; when ! follows, the value may be nil
+ I: inline struct [void*]
+ &: block [mrb_value] &! raises exception if no block given
*: rest argument [mrb_value*,mrb_int] The rest of the arguments as an array; *! avoid copy of the stack
|: optional Following arguments are optional
?: optional given [mrb_bool] true if preceding argument (optional) is given
+ ':': keyword args [mrb_kwargs const] Get keyword arguments
*/
MRB_API mrb_int
mrb_get_args(mrb_state *mrb, const char *format, ...)
@@ -602,6 +602,9 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_bool opt = FALSE;
mrb_bool opt_skip = TRUE;
mrb_bool given = TRUE;
+ mrb_value kdict;
+ mrb_bool reqkarg = FALSE;
+ mrb_int needargc = 0;
va_start(ap, format);
@@ -615,23 +618,39 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
break;
case '*':
opt_skip = FALSE;
+ if (!reqkarg) reqkarg = strchr(fmt, ':') ? TRUE : FALSE;
goto check_exit;
case '!':
break;
case '&': case '?':
if (opt) opt_skip = FALSE;
break;
+ case ':':
+ reqkarg = TRUE;
+ break;
default:
+ if (!opt) needargc ++;
break;
}
}
check_exit:
+ if (reqkarg && argc > needargc && mrb_hash_p(kdict = ARGV[argc - 1])) {
+ mrb_hash_check_kdict(mrb, kdict);
+ argc --;
+ }
+ else {
+ kdict = mrb_nil_value();
+ }
+
opt = FALSE;
i = 0;
while ((c = *format++)) {
+ mrb_value *argv = ARGV;
+ mrb_bool altmode;
+
switch (c) {
- case '|': case '*': case '&': case '?':
+ case '|': case '*': case '&': case '?': case ':':
break;
default:
if (argc <= i) {
@@ -645,6 +664,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
break;
}
+ if (*format == '!') {
+ format ++;
+ altmode = TRUE;
+ }
+ else {
+ altmode = FALSE;
+ }
+
switch (c) {
case 'o':
{
@@ -652,7 +679,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
p = va_arg(ap, mrb_value*);
if (i < argc) {
- *p = ARGV[arg_i++];
+ *p = argv[arg_i++];
i++;
}
}
@@ -665,9 +692,9 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
if (i < argc) {
mrb_value ss;
- ss = ARGV[arg_i++];
+ ss = argv[arg_i++];
if (!class_ptr_p(ss)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "%S is not class/module", ss);
+ mrb_raisef(mrb, E_TYPE_ERROR, "%v is not class/module", ss);
}
*p = ss;
i++;
@@ -679,17 +706,12 @@ 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(ARGV[arg_i])) {
- *p = ARGV[arg_i++];
- i++;
- break;
- }
- }
if (i < argc) {
- *p = to_str(mrb, ARGV[arg_i++]);
+ *p = argv[arg_i++];
i++;
+ if (!(altmode && mrb_nil_p(*p))) {
+ mrb_to_str(mrb, *p);
+ }
}
}
break;
@@ -698,17 +720,12 @@ 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(ARGV[arg_i])) {
- *p = ARGV[arg_i++];
- i++;
- break;
- }
- }
if (i < argc) {
- *p = to_ary(mrb, ARGV[arg_i++]);
+ *p = argv[arg_i++];
i++;
+ if (!(altmode && mrb_nil_p(*p))) {
+ *p = to_ary(mrb, *p);
+ }
}
}
break;
@@ -717,17 +734,12 @@ 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(ARGV[arg_i])) {
- *p = ARGV[arg_i++];
- i++;
- break;
- }
- }
if (i < argc) {
- *p = to_hash(mrb, ARGV[arg_i++]);
+ *p = argv[arg_i++];
i++;
+ if (!(altmode && mrb_nil_p(*p))) {
+ *p = to_hash(mrb, *p);
+ }
}
}
break;
@@ -739,20 +751,18 @@ 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(ARGV[arg_i])) {
+ if (i < argc) {
+ ss = argv[arg_i++];
+ i++;
+ if (altmode && mrb_nil_p(ss)) {
*ps = NULL;
*pl = 0;
- i++; arg_i++;
- break;
}
- }
- if (i < argc) {
- ss = to_str(mrb, ARGV[arg_i++]);
- *ps = RSTRING_PTR(ss);
- *pl = RSTRING_LEN(ss);
- i++;
+ else {
+ mrb_to_str(mrb, ss);
+ *ps = RSTRING_PTR(ss);
+ *pl = RSTRING_LEN(ss);
+ }
}
}
break;
@@ -762,18 +772,16 @@ 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(ARGV[arg_i])) {
- *ps = NULL;
- i++; arg_i++;
- break;
- }
- }
if (i < argc) {
- ss = to_str(mrb, ARGV[arg_i++]);
- *ps = mrb_string_value_cstr(mrb, &ss);
+ ss = argv[arg_i++];
i++;
+ if (altmode && mrb_nil_p(ss)) {
+ *ps = NULL;
+ }
+ else {
+ mrb_to_str(mrb, ss);
+ *ps = RSTRING_CSTR(mrb, ss);
+ }
}
}
break;
@@ -786,21 +794,19 @@ 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(ARGV[arg_i])) {
+ if (i < argc) {
+ aa = argv[arg_i++];
+ i++;
+ if (altmode && mrb_nil_p(aa)) {
*pb = 0;
*pl = 0;
- i++; arg_i++;
- break;
}
- }
- if (i < argc) {
- aa = to_ary(mrb, ARGV[arg_i++]);
- a = mrb_ary_ptr(aa);
- *pb = ARY_PTR(a);
- *pl = ARY_LEN(a);
- i++;
+ else {
+ aa = to_ary(mrb, aa);
+ a = mrb_ary_ptr(aa);
+ *pb = ARY_PTR(a);
+ *pl = ARY_LEN(a);
+ }
}
}
break;
@@ -811,10 +817,10 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
p = va_arg(ap, void**);
if (i < argc) {
- ss = ARGV[arg_i];
- if (mrb_type(ss) != MRB_TT_ISTRUCT)
+ ss = argv[arg_i];
+ if (!mrb_istruct_p(ss))
{
- mrb_raisef(mrb, E_TYPE_ERROR, "%S is not inline struct", ss);
+ mrb_raisef(mrb, E_TYPE_ERROR, "%v is not inline struct", ss);
}
*p = mrb_istruct_ptr(ss);
arg_i++;
@@ -829,7 +835,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
p = va_arg(ap, mrb_float*);
if (i < argc) {
- *p = mrb_to_flo(mrb, ARGV[arg_i]);
+ *p = mrb_to_flo(mrb, argv[arg_i]);
arg_i++;
i++;
}
@@ -842,29 +848,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
p = va_arg(ap, mrb_int*);
if (i < argc) {
- switch (mrb_type(ARGV[arg_i])) {
- case MRB_TT_FIXNUM:
- *p = mrb_fixnum(ARGV[arg_i]);
- break;
-#ifndef MRB_WITHOUT_FLOAT
- case MRB_TT_FLOAT:
- {
- mrb_float f = mrb_float(ARGV[arg_i]);
-
- if (!FIXABLE_FLOAT(f)) {
- mrb_raise(mrb, E_RANGE_ERROR, "float too big for int");
- }
- *p = (mrb_int)f;
- }
- break;
-#endif
- case MRB_TT_STRING:
- mrb_raise(mrb, E_TYPE_ERROR, "no implicit conversion of String into Integer");
- break;
- default:
- *p = mrb_fixnum(mrb_Integer(mrb, ARGV[arg_i]));
- break;
- }
+ *p = mrb_fixnum(mrb_to_int(mrb, argv[arg_i]));
arg_i++;
i++;
}
@@ -875,7 +859,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_bool *boolp = va_arg(ap, mrb_bool*);
if (i < argc) {
- mrb_value b = ARGV[arg_i++];
+ mrb_value b = argv[arg_i++];
*boolp = mrb_test(b);
i++;
}
@@ -889,7 +873,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
if (i < argc) {
mrb_value ss;
- ss = ARGV[arg_i++];
+ ss = argv[arg_i++];
*symp = to_sym(mrb, ss);
i++;
}
@@ -902,17 +886,15 @@ 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(ARGV[arg_i])) {
+ if (i < argc) {
+ mrb_value dd = argv[arg_i++];
+ i++;
+ if (altmode && mrb_nil_p(dd)) {
*datap = 0;
- i++; arg_i++;
- break;
}
- }
- if (i < argc) {
- *datap = mrb_data_get_ptr(mrb, ARGV[arg_i++], type);
- ++i;
+ else {
+ *datap = mrb_data_get_ptr(mrb, dd, type);
+ }
}
}
break;
@@ -928,11 +910,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
else {
bp = mrb->c->stack + mrb->c->ci->argc + 1;
}
- if (*format == '!') {
- format ++;
- if (mrb_nil_p(*bp)) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
- }
+ if (altmode && mrb_nil_p(*bp)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
}
*p = *bp;
}
@@ -954,22 +933,18 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
{
mrb_value **var;
mrb_int *pl;
- mrb_bool nocopy = array_argv ? TRUE : FALSE;
+ mrb_bool nocopy = altmode || array_argv ? TRUE : FALSE;
- if (*format == '!') {
- format++;
- nocopy = TRUE;
- }
var = va_arg(ap, mrb_value**);
pl = va_arg(ap, mrb_int*);
if (argc > i) {
*pl = argc-i;
if (*pl > 0) {
if (nocopy) {
- *var = ARGV+arg_i;
+ *var = argv+arg_i;
}
else {
- mrb_value args = mrb_ary_new_from_values(mrb, *pl, ARGV+arg_i);
+ mrb_value args = mrb_ary_new_from_values(mrb, *pl, argv+arg_i);
RARRAY(args)->c = NULL;
*var = RARRAY_PTR(args);
}
@@ -983,8 +958,64 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
}
break;
+
+ case ':':
+ {
+ mrb_value ksrc = mrb_hash_p(kdict) ? mrb_hash_dup(mrb, kdict) : mrb_hash_new(mrb);
+ const mrb_kwargs *kwargs = va_arg(ap, const mrb_kwargs*);
+ mrb_value *rest;
+
+ if (kwargs == NULL) {
+ rest = NULL;
+ }
+ else {
+ uint32_t kwnum = kwargs->num;
+ uint32_t required = kwargs->required;
+ const char *const *kname = kwargs->table;
+ mrb_value *values = kwargs->values;
+ uint32_t j;
+ const uint32_t keyword_max = 40;
+
+ if (kwnum > keyword_max || required > kwnum) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "keyword number is too large");
+ }
+
+ for (j = required; j > 0; j --, kname ++, values ++) {
+ mrb_value k = mrb_symbol_value(mrb_intern_cstr(mrb, *kname));
+ if (!mrb_hash_key_p(mrb, ksrc, k)) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "missing keyword: %s", *kname);
+ }
+ *values = mrb_hash_delete_key(mrb, ksrc, k);
+ mrb_gc_protect(mrb, *values);
+ }
+
+ for (j = kwnum - required; j > 0; j --, kname ++, values ++) {
+ mrb_value k = mrb_symbol_value(mrb_intern_cstr(mrb, *kname));
+ if (mrb_hash_key_p(mrb, ksrc, k)) {
+ *values = mrb_hash_delete_key(mrb, ksrc, k);
+ mrb_gc_protect(mrb, *values);
+ }
+ else {
+ *values = mrb_undef_value();
+ }
+ }
+
+ rest = kwargs->rest;
+ }
+
+ if (rest) {
+ *rest = ksrc;
+ }
+ else if (!mrb_hash_empty_p(mrb, ksrc)) {
+ ksrc = mrb_hash_keys(mrb, ksrc);
+ ksrc = RARRAY_PTR(ksrc)[0];
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "unknown keyword: %v", ksrc);
+ }
+ }
+ break;
+
default:
- mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %S", mrb_str_new(mrb, &c, 1));
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid argument specifier %c", c);
break;
}
}
@@ -1090,8 +1121,8 @@ include_module_at(mrb_state *mrb, struct RClass *c, struct RClass *ins_pos, stru
MRB_API void
mrb_include_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
{
- int changed = include_module_at(mrb, c, find_origin(c), m, 1);
- if (changed < 0) {
+ mrb_check_frozen(mrb, c);
+ if (include_module_at(mrb, c, find_origin(c), m, 1) < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "cyclic include detected");
}
}
@@ -1102,6 +1133,7 @@ mrb_prepend_module(mrb_state *mrb, struct RClass *c, struct RClass *m)
struct RClass *origin;
int changed = 0;
+ mrb_check_frozen(mrb, c);
if (!(c->flags & MRB_FL_CLASS_IS_PREPENDED)) {
origin = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_ICLASS, c);
origin->flags |= MRB_FL_CLASS_IS_ORIGIN | MRB_FL_CLASS_IS_INHERITED;
@@ -1372,25 +1404,57 @@ mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid)
m = mrb_method_search_vm(mrb, &c, mid);
if (MRB_METHOD_UNDEF_P(m)) {
- mrb_value inspect = mrb_funcall(mrb, mrb_obj_value(c), "inspect", 0);
- if (mrb_string_p(inspect) && RSTRING_LEN(inspect) > 64) {
- inspect = mrb_any_to_s(mrb, mrb_obj_value(c));
- }
- mrb_name_error(mrb, mid, "undefined method '%S' for class %S",
- mrb_sym2str(mrb, mid), inspect);
+ mrb_name_error(mrb, mid, "undefined method '%n' for class %C", mid, c);
}
return m;
}
+#define ONSTACK_ALLOC_MAX 32
+
+static mrb_sym
+prepare_name_common(mrb_state *mrb, mrb_sym sym, const char *prefix, const char *suffix)
+{
+ char onstack[ONSTACK_ALLOC_MAX];
+ mrb_int sym_len;
+ const char *sym_str = mrb_sym_name_len(mrb, sym, &sym_len);
+ size_t prefix_len = prefix ? strlen(prefix) : 0;
+ size_t suffix_len = suffix ? strlen(suffix) : 0;
+ size_t name_len = sym_len + prefix_len + suffix_len;
+ char *buf = name_len > sizeof(onstack) ? (char *)mrb_alloca(mrb, name_len) : onstack;
+ char *p = buf;
+
+ if (prefix_len > 0) {
+ memcpy(p, prefix, prefix_len);
+ p += prefix_len;
+ }
+
+ memcpy(p, sym_str, sym_len);
+ p += sym_len;
+
+ if (suffix_len > 0) {
+ memcpy(p, suffix, suffix_len);
+ p += suffix_len;
+ }
+
+ return mrb_intern(mrb, buf, name_len);
+}
+
static mrb_value
-attr_reader(mrb_state *mrb, mrb_value obj)
+prepare_ivar_name(mrb_state *mrb, mrb_sym sym)
{
- mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
- return mrb_iv_get(mrb, obj, to_sym(mrb, name));
+ sym = prepare_name_common(mrb, sym, "@", NULL);
+ mrb_iv_name_sym_check(mrb, sym);
+ return mrb_symbol_value(sym);
+}
+
+static mrb_sym
+prepare_writer_name(mrb_state *mrb, mrb_sym sym)
+{
+ return prepare_name_common(mrb, sym, NULL, "=");
}
static mrb_value
-mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod)
+mod_attr_define(mrb_state *mrb, mrb_value mod, mrb_value (*accessor)(mrb_state *, mrb_value), mrb_sym (*access_name)(mrb_state *, mrb_sym))
{
struct RClass *c = mrb_class_ptr(mod);
mrb_value *argv;
@@ -1400,20 +1464,18 @@ mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod)
mrb_get_args(mrb, "*", &argv, &argc);
ai = mrb_gc_arena_save(mrb);
for (i=0; i<argc; i++) {
- mrb_value name, str;
- mrb_sym method, sym;
+ mrb_value name;
+ mrb_sym method;
struct RProc *p;
mrb_method_t m;
method = to_sym(mrb, argv[i]);
- name = mrb_sym2str(mrb, method);
- str = mrb_str_new_capa(mrb, RSTRING_LEN(name)+1);
- mrb_str_cat_lit(mrb, str, "@");
- mrb_str_cat_str(mrb, str, name);
- sym = mrb_intern_str(mrb, str);
- mrb_iv_name_sym_check(mrb, sym);
- name = mrb_symbol_value(sym);
- p = mrb_proc_new_cfunc_with_env(mrb, attr_reader, 1, &name);
+ name = prepare_ivar_name(mrb, method);
+ if (access_name) {
+ method = access_name(mrb, method);
+ }
+
+ p = mrb_proc_new_cfunc_with_env(mrb, accessor, 1, &name);
MRB_METHOD_FROM_PROC(m, p);
mrb_define_method_raw(mrb, c, method, m);
mrb_gc_arena_restore(mrb, ai);
@@ -1422,6 +1484,19 @@ mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod)
}
static mrb_value
+attr_reader(mrb_state *mrb, mrb_value obj)
+{
+ mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
+ return mrb_iv_get(mrb, obj, to_sym(mrb, name));
+}
+
+static mrb_value
+mrb_mod_attr_reader(mrb_state *mrb, mrb_value mod)
+{
+ return mod_attr_define(mrb, mod, attr_reader, NULL);
+}
+
+static mrb_value
attr_writer(mrb_state *mrb, mrb_value obj)
{
mrb_value name = mrb_proc_cfunc_env_get(mrb, 0);
@@ -1435,42 +1510,7 @@ attr_writer(mrb_state *mrb, mrb_value obj)
static mrb_value
mrb_mod_attr_writer(mrb_state *mrb, mrb_value mod)
{
- struct RClass *c = mrb_class_ptr(mod);
- mrb_value *argv;
- mrb_int argc, i;
- int ai;
-
- mrb_get_args(mrb, "*", &argv, &argc);
- ai = mrb_gc_arena_save(mrb);
- for (i=0; i<argc; i++) {
- mrb_value name, str, attr;
- mrb_sym method, sym;
- struct RProc *p;
- mrb_method_t m;
-
- method = to_sym(mrb, argv[i]);
-
- /* prepare iv name (@name) */
- name = mrb_sym2str(mrb, method);
- str = mrb_str_new_capa(mrb, RSTRING_LEN(name)+1);
- mrb_str_cat_lit(mrb, str, "@");
- mrb_str_cat_str(mrb, str, name);
- sym = mrb_intern_str(mrb, str);
- mrb_iv_name_sym_check(mrb, sym);
- attr = mrb_symbol_value(sym);
-
- /* prepare method name (name=) */
- str = mrb_str_new_capa(mrb, RSTRING_LEN(str));
- mrb_str_cat_str(mrb, str, name);
- mrb_str_cat_lit(mrb, str, "=");
- method = mrb_intern_str(mrb, str);
-
- p = mrb_proc_new_cfunc_with_env(mrb, attr_writer, 1, &attr);
- MRB_METHOD_FROM_PROC(m, p);
- mrb_define_method_raw(mrb, c, method, m);
- mrb_gc_arena_restore(mrb, ai);
- }
- return mrb_nil_value();
+ return mod_attr_define(mrb, mod, attr_writer, prepare_writer_name);
}
static mrb_value
@@ -1485,7 +1525,7 @@ mrb_instance_alloc(mrb_state *mrb, mrb_value cv)
if (ttype == 0) ttype = MRB_TT_OBJECT;
if (ttype <= MRB_TT_CPTR) {
- mrb_raisef(mrb, E_TYPE_ERROR, "can't create instance of %S", cv);
+ mrb_raisef(mrb, E_TYPE_ERROR, "can't create instance of %v", cv);
}
o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
return mrb_obj_value(o);
@@ -1503,29 +1543,20 @@ mrb_instance_alloc(mrb_state *mrb, mrb_value cv)
*
*/
-MRB_API mrb_value
+mrb_value
mrb_instance_new(mrb_state *mrb, mrb_value cv)
{
mrb_value obj, blk;
mrb_value *argv;
mrb_int argc;
mrb_sym init;
- mrb_method_t m;
- mrb_get_args(mrb, "*&", &argv, &argc, &blk);
+ mrb_get_args(mrb, "*!&", &argv, &argc, &blk);
obj = mrb_instance_alloc(mrb, cv);
init = mrb_intern_lit(mrb, "initialize");
- m = mrb_method_search(mrb, mrb_class(mrb, obj), init);
- if (MRB_METHOD_CFUNC_P(m)) {
- mrb_func_t f = MRB_METHOD_CFUNC(m);
- if (f != mrb_bob_init) {
- f(mrb, obj);
- }
- }
- else {
+ if (!mrb_func_basic_p(mrb, obj, init, mrb_bob_init)) {
mrb_funcall_with_block(mrb, obj, init, argc, argv, blk);
}
-
return obj;
}
@@ -1569,7 +1600,10 @@ mrb_class_new_class(mrb_state *mrb, mrb_value cv)
}
new_class = mrb_obj_value(mrb_class_new(mrb, mrb_class_ptr(super)));
mid = mrb_intern_lit(mrb, "initialize");
- if (!mrb_func_basic_p(mrb, new_class, mid, mrb_bob_init)) {
+ if (mrb_func_basic_p(mrb, new_class, mid, mrb_class_initialize)) {
+ mrb_class_initialize(mrb, new_class);
+ }
+ else {
mrb_funcall_with_block(mrb, new_class, mid, n, &super, blk);
}
mrb_class_inherited(mrb, mrb_class_ptr(super), mrb_class_ptr(new_class));
@@ -1682,9 +1716,9 @@ mrb_class_path(mrb_state *mrb, struct RClass *c)
}
else if (mrb_symbol_p(path)) {
/* toplevel class/module */
- return mrb_sym2str(mrb, mrb_symbol(path));
+ return mrb_sym_str(mrb, mrb_symbol(path));
}
- return mrb_str_dup(mrb, path);
+ return path;
}
MRB_API struct RClass*
@@ -1721,7 +1755,7 @@ static void
mrb_check_inheritable(mrb_state *mrb, struct RClass *super)
{
if (super->tt != MRB_TT_CLASS) {
- mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%S given)", mrb_obj_value(super));
+ mrb_raisef(mrb, E_TYPE_ERROR, "superclass must be a Class (%C given)", super);
}
if (super->tt == MRB_TT_SCLASS) {
mrb_raise(mrb, E_TYPE_ERROR, "can't make subclass of singleton class");
@@ -1790,11 +1824,31 @@ mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b)
{
mrb_method_t m = mrb_method_search(mrb, c, b);
+ if (!MRB_METHOD_CFUNC_P(m)) {
+ struct RProc *p = MRB_METHOD_PROC(m);
+
+ if (MRB_PROC_ENV_P(p)) {
+ MRB_PROC_ENV(p)->mid = b;
+ }
+ else {
+ struct RClass *tc = MRB_PROC_TARGET_CLASS(p);
+ struct REnv *e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, NULL);
+
+ e->mid = b;
+ if (tc) {
+ e->c = tc;
+ mrb_field_write_barrier(mrb, (struct RBasic*)e, (struct RBasic*)tc);
+ }
+ p->e.env = e;
+ p->flags |= MRB_PROC_ENVSET;
+ }
+ }
mrb_define_method_raw(mrb, c, a, m);
}
/*!
* Defines an alias of a method.
+ * \param mrb the mruby state
* \param klass the class which the original method belongs to
* \param name1 a new name for the method
* \param name2 the original name of the method
@@ -1818,7 +1872,7 @@ mrb_value
mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
{
- if (mrb_type(klass) == MRB_TT_SCLASS) {
+ if (mrb_sclass_p(klass)) {
mrb_value v = mrb_iv_get(mrb, klass, mrb_intern_lit(mrb, "__attached__"));
mrb_value str = mrb_str_new_lit(mrb, "#<Class:");
@@ -1843,27 +1897,31 @@ mrb_mod_alias(mrb_state *mrb, mrb_value mod)
mrb_get_args(mrb, "nn", &new_name, &old_name);
mrb_alias_method(mrb, c, new_name, old_name);
- return mrb_nil_value();
+ return mod;
+}
+
+static void
+undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a)
+{
+ mrb_method_t m;
+
+ MRB_METHOD_FROM_PROC(m, NULL);
+ mrb_define_method_raw(mrb, c, a, m);
}
void
mrb_undef_method_id(mrb_state *mrb, struct RClass *c, mrb_sym a)
{
if (!mrb_obj_respond_to(mrb, c, a)) {
- mrb_name_error(mrb, a, "undefined method '%S' for class '%S'", mrb_sym2str(mrb, a), mrb_obj_value(c));
- }
- else {
- mrb_method_t m;
-
- MRB_METHOD_FROM_PROC(m, NULL);
- mrb_define_method_raw(mrb, c, a, m);
+ mrb_name_error(mrb, a, "undefined method '%n' for class '%C'", a, c);
}
+ undef_method(mrb, c, a);
}
MRB_API void
mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name)
{
- mrb_undef_method_id(mrb, c, mrb_intern_cstr(mrb, name));
+ undef_method(mrb, c, mrb_intern_cstr(mrb, name));
}
MRB_API void
@@ -1887,19 +1945,13 @@ mrb_mod_undef(mrb_state *mrb, mrb_value mod)
return mrb_nil_value();
}
-static mrb_bool
-const_name_p(mrb_state *mrb, const char *name, mrb_int len)
-{
- return len > 0 && ISUPPER(name[0]) && mrb_ident_p(name+1, len-1);
-}
-
static void
check_const_name_sym(mrb_state *mrb, mrb_sym id)
{
mrb_int len;
- const char *name = mrb_sym2name_len(mrb, id, &len);
- if (!const_name_p(mrb, name, len)) {
- mrb_name_error(mrb, id, "wrong constant name %S", mrb_sym2str(mrb, id));
+ const char *name = mrb_sym_name_len(mrb, id, &len);
+ if (!mrb_const_name_p(mrb, name, len)) {
+ mrb_name_error(mrb, id, "wrong constant name %n", id);
}
}
@@ -1956,7 +2008,7 @@ mrb_mod_const_get(mrb_state *mrb, mrb_value mod)
else {
off = end + 2;
if (off == len) { /* trailing "::" */
- mrb_name_error(mrb, id, "wrong constant name '%S'", path);
+ mrb_name_error(mrb, id, "wrong constant name '%v'", path);
}
}
}
@@ -1986,7 +2038,7 @@ mrb_mod_remove_const(mrb_state *mrb, mrb_value mod)
check_const_name_sym(mrb, id);
val = mrb_iv_remove(mrb, mod, id);
if (mrb_undef_p(val)) {
- mrb_name_error(mrb, id, "constant %S not defined", mrb_sym2str(mrb, id));
+ mrb_name_error(mrb, id, "constant %n not defined", id);
}
return val;
}
@@ -1999,13 +2051,10 @@ mrb_mod_const_missing(mrb_state *mrb, mrb_value mod)
mrb_get_args(mrb, "n", &sym);
if (mrb_class_real(mrb_class_ptr(mod)) != mrb->object_class) {
- mrb_name_error(mrb, sym, "uninitialized constant %S::%S",
- mod,
- mrb_sym2str(mrb, sym));
+ mrb_name_error(mrb, sym, "uninitialized constant %v::%n", mod, sym);
}
else {
- mrb_name_error(mrb, sym, "uninitialized constant %S",
- mrb_sym2str(mrb, sym));
+ mrb_name_error(mrb, sym, "uninitialized constant %n", sym);
}
/* not reached */
return mrb_nil_value();
@@ -2066,7 +2115,7 @@ mod_define_method(mrb_state *mrb, mrb_value self)
/* ignored */
break;
default:
- mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %S (expected Proc)", mrb_obj_value(mrb_obj_class(mrb, proc)));
+ mrb_raisef(mrb, E_TYPE_ERROR, "wrong argument type %T (expected Proc)", proc);
break;
}
if (mrb_nil_p(blk)) {
@@ -2099,6 +2148,14 @@ mrb_mod_eqq(mrb_state *mrb, mrb_value mod)
}
static mrb_value
+mrb_mod_dup(mrb_state *mrb, mrb_value self)
+{
+ mrb_value mod = mrb_obj_clone(mrb, self);
+ MRB_UNSET_FROZEN_FLAG(mrb_obj_ptr(mod));
+ return mod;
+}
+
+static mrb_value
mrb_mod_module_function(mrb_state *mrb, mrb_value mod)
{
mrb_value *argv;
@@ -2146,6 +2203,40 @@ inspect_main(mrb_state *mrb, mrb_value mod)
return mrb_str_new_lit(mrb, "main");
}
+static const mrb_code new_iseq[] = {
+ OP_ENTER, 0x0, 0x10, 0x1, /* OP_ENTER 0:0:1:0:0:0:1 */
+ OP_LOADSELF, 0x3, /* OP_LOADSELF R3 */
+ OP_SEND, 0x3, 0x0, 0x0, /* OP_SEND R3 :allocate 0 */
+ OP_MOVE, 0x0, 0x3, /* OP_MOVE R0 R3 */
+ OP_MOVE, 0x4, 0x1, /* OP_MOVE R4 R1 */
+ OP_MOVE, 0x5, 0x2, /* OP_MOVE R5 R2 */
+ OP_SENDVB, 0x3, 0x1, /* OP_SENDVB R4 :initialize */
+ OP_RETURN, 0x0 /* OP_RETURN R0 */
+};
+
+static void
+init_class_new(mrb_state *mrb, struct RClass *cls)
+{
+ struct RProc *p;
+ mrb_method_t m;
+ mrb_irep *new_irep = (mrb_irep*)mrb_malloc(mrb, sizeof(mrb_irep));
+ static const mrb_irep mrb_irep_zero = { 0 };
+
+ *new_irep = mrb_irep_zero;
+ new_irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*2);
+ new_irep->syms[0] = mrb_intern_lit(mrb, "allocate");
+ new_irep->syms[1] = mrb_intern_lit(mrb, "initialize");
+ new_irep->slen = 2;
+ new_irep->flags = MRB_ISEQ_NO_FREE;
+ new_irep->iseq = new_iseq;
+ new_irep->ilen = sizeof(new_iseq);
+ new_irep->nregs = 6;
+ new_irep->nlocals = 3;
+ p = mrb_proc_new(mrb, new_irep);
+ MRB_METHOD_FROM_PROC(m, p);
+ mrb_define_method_raw(mrb, cls, mrb_intern_lit(mrb, "new"), m);
+}
+
void
mrb_init_class(mrb_state *mrb)
{
@@ -2168,7 +2259,6 @@ mrb_init_class(mrb_state *mrb)
/* name basic classes */
mrb_define_const(mrb, bob, "BasicObject", mrb_obj_value(bob));
- mrb_define_const(mrb, obj, "BasicObject", mrb_obj_value(bob));
mrb_define_const(mrb, obj, "Object", mrb_obj_value(obj));
mrb_define_const(mrb, obj, "Module", mrb_obj_value(mod));
mrb_define_const(mrb, obj, "Class", mrb_obj_value(cls));
@@ -2188,15 +2278,18 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, bob, "==", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.1 */
mrb_define_method(mrb, bob, "!=", mrb_obj_not_equal_m, MRB_ARGS_REQ(1));
mrb_define_method(mrb, bob, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.4 */
- mrb_define_method(mrb, bob, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.5 */
- mrb_define_method(mrb, bob, "instance_eval", mrb_obj_instance_eval, MRB_ARGS_ANY()); /* 15.3.1.3.18 */
+ mrb_define_method(mrb, bob, "__send__", mrb_f_send, MRB_ARGS_REQ(1)|MRB_ARGS_REST()|MRB_ARGS_BLOCK()); /* 15.3.1.3.5 */
+ mrb_define_method(mrb, bob, "equal?", mrb_obj_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.11 */
+ mrb_define_method(mrb, bob, "instance_eval", mrb_obj_instance_eval, MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK()); /* 15.3.1.3.18 */
- mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, MRB_ARGS_OPT(1));
+ mrb_define_class_method(mrb, cls, "new", mrb_class_new_class, MRB_ARGS_OPT(1)|MRB_ARGS_BLOCK());
+ mrb_define_method(mrb, cls, "allocate", mrb_instance_alloc, MRB_ARGS_NONE());
mrb_define_method(mrb, cls, "superclass", mrb_class_superclass, MRB_ARGS_NONE()); /* 15.2.3.3.4 */
- mrb_define_method(mrb, cls, "new", mrb_instance_new, MRB_ARGS_ANY()); /* 15.2.3.3.3 */
mrb_define_method(mrb, cls, "initialize", mrb_class_initialize, MRB_ARGS_OPT(1)); /* 15.2.3.3.1 */
mrb_define_method(mrb, cls, "inherited", mrb_bob_init, MRB_ARGS_REQ(1));
+ init_class_new(mrb, cls);
+
MRB_SET_INSTANCE_TT(mod, MRB_TT_MODULE);
mrb_define_method(mrb, mod, "extend_object", mrb_mod_extend_object, MRB_ARGS_REQ(1)); /* 15.2.2.4.25 */
mrb_define_method(mrb, mod, "extended", mrb_bob_init, MRB_ARGS_REQ(1)); /* 15.2.2.4.26 */
@@ -2226,7 +2319,8 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, mod, "const_missing", mrb_mod_const_missing, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mod, "method_defined?", mrb_mod_method_defined, MRB_ARGS_REQ(1)); /* 15.2.2.4.34 */
mrb_define_method(mrb, mod, "define_method", mod_define_method, MRB_ARGS_ARG(1,1));
- mrb_define_method(mrb, mod, "===", mrb_mod_eqq, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, mod, "===", mrb_mod_eqq, MRB_ARGS_REQ(1)); /* 15.2.2.4.7 */
+ mrb_define_method(mrb, mod, "dup", mrb_mod_dup, MRB_ARGS_NONE());
mrb_undef_method(mrb, cls, "append_features");
mrb_undef_method(mrb, cls, "extend_object");