summaryrefslogtreecommitdiffhomepage
path: root/src/class.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/class.c')
-rw-r--r--src/class.c537
1 files changed, 295 insertions, 242 deletions
diff --git a/src/class.c b/src/class.c
index 4994b0045..33515de2c 100644
--- a/src/class.c
+++ b/src/class.c
@@ -4,18 +4,19 @@
** See Copyright Notice in mruby.h
*/
-#include "mruby.h"
-#include <stdarg.h>
#include <ctype.h>
+#include <stdarg.h>
+#include "mruby.h"
#include "mruby/array.h"
#include "mruby/class.h"
#include "mruby/numeric.h"
#include "mruby/proc.h"
#include "mruby/string.h"
#include "mruby/variable.h"
-#include "error.h"
+#include "mruby/error.h"
+#include "mruby/data.h"
-KHASH_DEFINE(mt, mrb_sym, struct RProc*, 1, kh_int_hash_func, kh_int_hash_equal)
+KHASH_DEFINE(mt, mrb_sym, struct RProc*, TRUE, kh_int_hash_func, kh_int_hash_equal)
void
mrb_gc_mark_mt(mrb_state *mrb, struct RClass *c)
@@ -46,16 +47,27 @@ mrb_gc_mark_mt_size(mrb_state *mrb, struct RClass *c)
void
mrb_gc_free_mt(mrb_state *mrb, struct RClass *c)
{
- kh_destroy(mt, c->mt);
+ kh_destroy(mt, mrb, c->mt);
}
-void
-mrb_name_class(mrb_state *mrb, struct RClass *c, mrb_sym name)
+static void
+name_class(mrb_state *mrb, struct RClass *c, mrb_sym name)
{
mrb_obj_iv_set(mrb, (struct RObject*)c,
- mrb_intern2(mrb, "__classid__", 11), mrb_symbol_value(name));
+ mrb_intern_lit(mrb, "__classid__"), mrb_symbol_value(name));
+}
+
+static void
+setup_class(mrb_state *mrb, struct RClass *outer, struct RClass *c, mrb_sym id)
+{
+ name_class(mrb, c, id);
+ mrb_obj_iv_set(mrb, (struct RObject*)outer, id, mrb_obj_value(c));
+ if (outer != mrb->object_class) {
+ mrb_obj_iv_set(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"),
+ mrb_obj_value(outer));
+ }
}
-
+
#define make_metaclass(mrb, c) prepare_singleton_class((mrb), (struct RBasic*)(c))
static void
@@ -89,34 +101,25 @@ prepare_singleton_class(mrb_state *mrb, struct RBasic *o)
o->c = sc;
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_intern2(mrb, "__attached__", 12), mrb_obj_value(o));
+ mrb_obj_iv_set(mrb, (struct RObject*)sc, mrb_intern_lit(mrb, "__attached__"), mrb_obj_value(o));
}
-struct RClass*
-mrb_define_module_id(mrb_state *mrb, mrb_sym name)
+static struct RClass *
+class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
{
- struct RClass *m = mrb_module_new(mrb);
-
- mrb_obj_iv_set(mrb, (struct RObject*)mrb->object_class,
- name, mrb_obj_value(m));
- mrb_name_class(mrb, m, name);
+ mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
- return m;
+ mrb_check_type(mrb, c, MRB_TT_CLASS);
+ return mrb_class_ptr(c);
}
-struct RClass*
-mrb_define_module(mrb_state *mrb, const char *name)
+static struct RClass *
+module_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
{
- return mrb_define_module_id(mrb, mrb_intern_cstr(mrb, name));
-}
+ mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
-static void
-setup_class(mrb_state *mrb, mrb_value outer, struct RClass *c, mrb_sym id)
-{
- mrb_name_class(mrb, c, id);
- mrb_const_set(mrb, outer, id, mrb_obj_value(c));
- mrb_obj_iv_set(mrb, (struct RObject*)c,
- mrb_intern2(mrb, "__outer__", 9), outer);
+ mrb_check_type(mrb, c, MRB_TT_MODULE);
+ return mrb_class_ptr(c);
}
struct RClass*
@@ -124,41 +127,84 @@ mrb_class_outer_module(mrb_state *mrb, struct RClass *c)
{
mrb_value outer;
- outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern2(mrb, "__outer__", 9));
+ outer = mrb_obj_iv_get(mrb, (struct RObject*)c, mrb_intern_lit(mrb, "__outer__"));
if (mrb_nil_p(outer)) return 0;
return mrb_class_ptr(outer);
}
+static struct RClass*
+define_module(mrb_state *mrb, mrb_sym name, struct RClass *outer)
+{
+ struct RClass *m;
+
+ if (mrb_const_defined_at(mrb, outer, name)) {
+ return module_from_sym(mrb, outer, name);
+ }
+ m = mrb_module_new(mrb);
+ setup_class(mrb, outer, m, name);
+
+ return m;
+}
+
+struct RClass*
+mrb_define_module_id(mrb_state *mrb, mrb_sym name)
+{
+ return define_module(mrb, name, mrb->object_class);
+}
+
+struct RClass*
+mrb_define_module(mrb_state *mrb, const char *name)
+{
+ return define_module(mrb, mrb_intern_cstr(mrb, name), mrb->object_class);
+}
+
struct RClass*
mrb_vm_define_module(mrb_state *mrb, mrb_value outer, mrb_sym id)
{
- struct RClass *c;
- mrb_value v;
+ return define_module(mrb, id, mrb_class_ptr(outer));
+}
- if (mrb_const_defined(mrb, outer, id)) {
- v = mrb_const_get(mrb, outer, id);
- c = mrb_class_ptr(v);
- }
- else {
- c = mrb_module_new(mrb);
- setup_class(mrb, outer, c, id);
- }
+struct RClass *
+mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name)
+{
+ mrb_sym id = mrb_intern_cstr(mrb, name);
+ struct RClass * c = define_module(mrb, id, outer);
+
+ setup_class(mrb, outer, c, id);
return c;
}
-struct RClass*
-mrb_define_class_id(mrb_state *mrb, mrb_sym name, struct RClass *super)
+static struct RClass*
+define_class(mrb_state *mrb, mrb_sym name, struct RClass *super, struct RClass *outer)
{
- struct RClass *c = mrb_class_new(mrb, super);
+ struct RClass * c;
+
+ if (mrb_const_defined_at(mrb, outer, name)) {
+ c = class_from_sym(mrb, outer, name);
+ 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));
+ }
+ return c;
+ }
- mrb_obj_iv_set(mrb, (struct RObject*)mrb->object_class,
- name, mrb_obj_value(c));
- mrb_name_class(mrb, c, name);
+ c = mrb_class_new(mrb, super);
+ setup_class(mrb, outer, c, name);
return c;
}
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));
+ }
+ return define_class(mrb, name, super, mrb->object_class);
+}
+
+struct RClass*
mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super)
{
return mrb_define_class_id(mrb, mrb_intern_cstr(mrb, name), super);
@@ -167,24 +213,8 @@ mrb_define_class(mrb_state *mrb, const char *name, struct RClass *super)
struct RClass*
mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id)
{
- struct RClass *c, *s;
-
- if (mrb_const_defined(mrb, outer, id)) {
- mrb_value v = mrb_const_get(mrb, outer, id);
-
- mrb_check_type(mrb, v, MRB_TT_CLASS);
- c = mrb_class_ptr(v);
- 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)", super);
- }
-
- if (!c->super || mrb_class_ptr(super) != mrb_class_real(c->super)) {
- mrb_raisef(mrb, E_TYPE_ERROR, "superclass mismatch for class %S", mrb_sym2str(mrb, id));
- }
- }
- return c;
- }
+ struct RClass *s;
+ struct RClass *c;
if (!mrb_nil_p(super)) {
if (mrb_type(super) != MRB_TT_CLASS) {
@@ -193,12 +223,18 @@ mrb_vm_define_class(mrb_state *mrb, mrb_value outer, mrb_value super, mrb_sym id
s = mrb_class_ptr(super);
}
else {
- s = mrb->object_class;
+ s = 0;
}
-
- c = mrb_class_new(mrb, s);
- setup_class(mrb, outer, c, id);
- mrb_funcall(mrb, mrb_obj_value(s), "inherited", 1, mrb_obj_value(c));
+ switch (mrb_type(outer)) {
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ break;
+ default:
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", outer);
+ break;
+ }
+ c = define_class(mrb, id, s, mrb_class_ptr(outer));
+ mrb_funcall(mrb, mrb_obj_value(mrb_class_real(c->super)), "inherited", 1, mrb_obj_value(c));
return c;
}
@@ -213,15 +249,10 @@ mrb_class_defined(mrb_state *mrb, const char *name)
return mrb_const_defined(mrb, mrb_obj_value(mrb->object_class), mrb_symbol(sym));
}
-static struct RClass *
-class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
+struct RClass *
+mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
{
- mrb_value c = mrb_const_get(mrb, mrb_obj_value(klass), id);
-
- if (mrb_type(c) != MRB_TT_MODULE && mrb_type(c) != MRB_TT_CLASS) {
- mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a class/module", mrb_sym2str(mrb, id));
- }
- return mrb_class_ptr(c);
+ return class_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
}
struct RClass *
@@ -231,9 +262,15 @@ mrb_class_get(mrb_state *mrb, const char *name)
}
struct RClass *
-mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
+mrb_module_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
{
- return class_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
+ return module_from_sym(mrb, outer, mrb_intern_cstr(mrb, name));
+}
+
+struct RClass *
+mrb_module_get(mrb_state *mrb, const char *name)
+{
+ return mrb_module_get_under(mrb, mrb->object_class, name);
}
/*!
@@ -255,38 +292,17 @@ mrb_class_get_under(mrb_state *mrb, struct RClass *outer, const char *name)
struct RClass *
mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, struct RClass *super)
{
- struct RClass * c;
mrb_sym id = mrb_intern_cstr(mrb, name);
-
- if (mrb_const_defined_at(mrb, outer, id)) {
- c = class_from_sym(mrb, outer, id);
- if (mrb_class_real(c->super) != super) {
- mrb_name_error(mrb, id, "%S is already defined", name);
- }
- return c;
- }
- if (!super) {
- mrb_warn(mrb, "no super class for `%S::%S', Object assumed", outer, name);
- }
- c = mrb_class_new(mrb, super);
- setup_class(mrb, mrb_obj_value(outer), c, id);
-
- return c;
-}
-
-struct RClass *
-mrb_define_module_under(mrb_state *mrb, struct RClass *outer, const char *name)
-{
struct RClass * c;
- mrb_sym id = mrb_intern_cstr(mrb, name);
- if (mrb_const_defined_at(mrb, outer, id)) {
- c = class_from_sym(mrb, outer, id);
- return c;
+#if 0
+ if (!super) {
+ mrb_warn(mrb, "no super class for `%S::%S', Object assumed",
+ mrb_obj_value(outer), mrb_sym2str(mrb, id));
}
- c = mrb_module_new(mrb);
- setup_class(mrb, mrb_obj_value(outer), c, id);
-
+#endif
+ c = define_class(mrb, id, super, outer);
+ setup_class(mrb, outer, c, id);
return c;
}
@@ -297,7 +313,7 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, struct RPro
khiter_t k;
if (!h) h = c->mt = kh_init(mt, mrb);
- k = kh_put(mt, h, mid);
+ k = kh_put(mt, mrb, h, mid);
kh_value(h, k) = p;
if (p) {
mrb_field_write_barrier(mrb, (struct RBasic *)c, (struct RBasic *)p);
@@ -311,6 +327,7 @@ mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t f
int ai = mrb_gc_arena_save(mrb);
p = mrb_proc_new_cfunc(mrb, func);
+ p->target_class = c;
mrb_define_method_raw(mrb, c, mid, p);
mrb_gc_arena_restore(mrb, ai);
}
@@ -329,7 +346,7 @@ mrb_define_method_vm(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_value b
struct RProc *p;
if (!h) h = c->mt = kh_init(mt, mrb);
- k = kh_put(mt, h, name);
+ k = kh_put(mt, mrb, h, name);
p = mrb_proc_ptr(body);
kh_value(h, k) = p;
if (p) {
@@ -379,6 +396,7 @@ to_hash(mrb_state *mrb, mrb_value val)
string mruby type C type note
----------------------------------------------------------------------------------------------
o: Object [mrb_value]
+ C: class/module [mrb_value]
S: String [mrb_value]
A: Array [mrb_value]
H: Hash [mrb_value]
@@ -389,9 +407,11 @@ to_hash(mrb_state *mrb, mrb_value val)
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
&: Block [mrb_value]
*: rest argument [mrb_value*,int] Receive the rest of the arguments as an array.
|: optional Next argument of '|' and later are optional.
+ ?: optional given [mrb_bool] true if preceding argument (optional) is given.
*/
int
mrb_get_args(mrb_state *mrb, const char *format, ...)
@@ -401,7 +421,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_value *sp = mrb->c->stack + 1;
va_list ap;
int argc = mrb->c->ci->argc;
- int opt = 0;
+ mrb_bool opt = 0;
+ mrb_bool given = 1;
va_start(ap, format);
if (argc < 0) {
@@ -412,11 +433,16 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
while ((c = *format++)) {
switch (c) {
- case '|': case '*': case '&':
+ case '|': case '*': case '&': case '?':
break;
default:
- if (argc <= i && !opt) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
+ if (argc <= i) {
+ if (opt) {
+ given = 0;
+ }
+ else {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
+ }
}
break;
}
@@ -433,6 +459,29 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
}
break;
+ case 'C':
+ {
+ mrb_value *p;
+
+ p = va_arg(ap, mrb_value*);
+ if (i < argc) {
+ mrb_value ss;
+
+ ss = *sp++;
+ switch (mrb_type(ss)) {
+ case MRB_TT_CLASS:
+ case MRB_TT_MODULE:
+ case MRB_TT_SCLASS:
+ break;
+ default:
+ mrb_raisef(mrb, E_TYPE_ERROR, "%S is not class/module", ss);
+ break;
+ }
+ *p = ss;
+ i++;
+ }
+ }
+ break;
case 'S':
{
mrb_value *p;
@@ -469,7 +518,6 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
case 's':
{
mrb_value ss;
- struct RString *s;
char **ps = 0;
int *pl = 0;
@@ -477,9 +525,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
pl = va_arg(ap, int*);
if (i < argc) {
ss = to_str(mrb, *sp++);
- s = mrb_str_ptr(ss);
- *ps = s->ptr;
- *pl = s->len;
+ *ps = RSTRING_PTR(ss);
+ *pl = RSTRING_LEN(ss);
i++;
}
}
@@ -487,17 +534,12 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
case 'z':
{
mrb_value ss;
- struct RString *s;
char **ps;
ps = va_arg(ap, char**);
if (i < argc) {
ss = to_str(mrb, *sp++);
- s = mrb_str_ptr(ss);
- if (strlen(s->ptr) < s->len) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "String contains NUL");
- }
- *ps = s->ptr;
+ *ps = mrb_string_value_cstr(mrb, &ss);
i++;
}
}
@@ -526,25 +568,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
p = va_arg(ap, mrb_float*);
if (i < argc) {
- switch (mrb_type(*sp)) {
- case MRB_TT_FLOAT:
- *p = mrb_float(*sp);
- break;
- case MRB_TT_FIXNUM:
- *p = (mrb_float)mrb_fixnum(*sp);
- break;
- case MRB_TT_STRING:
- mrb_raise(mrb, E_TYPE_ERROR, "String can't be coerced into Float");
- break;
- default:
- {
- mrb_value tmp;
-
- tmp = mrb_convert_type(mrb, *sp, MRB_TT_FLOAT, "Float", "to_f");
- *p = mrb_float(tmp);
- }
- break;
- }
+ *p = mrb_to_flo(mrb, *sp);
sp++;
i++;
}
@@ -570,16 +594,11 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
*p = (mrb_int)f;
}
break;
- case MRB_TT_FALSE:
- *p = 0;
+ case MRB_TT_STRING:
+ mrb_raise(mrb, E_TYPE_ERROR, "no implicit conversion of String into Integer");
break;
default:
- {
- mrb_value tmp;
-
- tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int");
- *p = mrb_fixnum(tmp);
- }
+ *p = mrb_fixnum(mrb_Integer(mrb, *sp));
break;
}
sp++;
@@ -621,6 +640,19 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
}
}
break;
+ case 'd':
+ {
+ void** datap;
+ struct mrb_data_type const* type;
+
+ datap = va_arg(ap, void**);
+ type = va_arg(ap, struct mrb_data_type const*);
+ if (i < argc) {
+ *datap = mrb_data_get_ptr(mrb, *sp++, type);
+ ++i;
+ }
+ }
+ break;
case '&':
{
@@ -639,6 +671,14 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
case '|':
opt = 1;
break;
+ case '?':
+ {
+ mrb_bool *p;
+
+ p = va_arg(ap, mrb_bool*);
+ *p = given;
+ }
+ break;
case '*':
{
@@ -679,8 +719,13 @@ boot_defclass(mrb_state *mrb, struct RClass *super)
struct RClass *c;
c = (struct RClass*)mrb_obj_alloc(mrb, MRB_TT_CLASS, mrb->class_class);
- c->super = super ? super : mrb->object_class;
- mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)super);
+ if (super) {
+ c->super = super;
+ mrb_field_write_barrier(mrb, (struct RBasic*)c, (struct RBasic*)super);
+ }
+ else {
+ c->super = mrb->object_class;
+ }
c->mt = kh_init(mt, mrb);
return c;
}
@@ -734,7 +779,7 @@ mrb_mod_append_features(mrb_state *mrb, mrb_value mod)
mrb_value klass;
mrb_check_type(mrb, mod, MRB_TT_MODULE);
- mrb_get_args(mrb, "o", &klass);
+ mrb_get_args(mrb, "C", &klass);
mrb_include_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod));
return mod;
}
@@ -782,7 +827,7 @@ mrb_mod_include_p(mrb_state *mrb, mrb_value mod)
mrb_value mod2;
struct RClass *c = mrb_class_ptr(mod);
- mrb_get_args(mrb, "o", &mod2);
+ mrb_get_args(mrb, "C", &mod2);
mrb_check_type(mrb, mod2, MRB_TT_MODULE);
while (c) {
@@ -844,7 +889,7 @@ mrb_mod_included_modules(mrb_state *mrb, mrb_value self)
return result;
}
-mrb_value class_instance_method_list(mrb_state*, mrb_bool, struct RClass*, int);
+mrb_value mrb_class_instance_method_list(mrb_state*, mrb_bool, struct RClass*, int);
/* 15.2.2.4.33 */
/*
@@ -880,11 +925,9 @@ mrb_mod_instance_methods(mrb_state *mrb, mrb_value mod)
struct RClass *c = mrb_class_ptr(mod);
mrb_bool recur = TRUE;
mrb_get_args(mrb, "|b", &recur);
- return class_instance_method_list(mrb, recur, c, 0);
+ return mrb_class_instance_method_list(mrb, recur, c, 0);
}
-mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c);
-
/* 15.2.2.4.35 */
/*
* call-seq:
@@ -906,7 +949,7 @@ mrb_mod_module_eval(mrb_state *mrb, mrb_value mod)
mrb_raise(mrb, E_NOTIMP_ERROR, "module_eval/class_eval with string not implemented");
}
c = mrb_class_ptr(mod);
- return mrb_yield_internal(mrb, b, 0, 0, mod, c);
+ return mrb_yield_with_class(mrb, b, 0, 0, mod, c);
}
mrb_value
@@ -927,7 +970,7 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v)
return mrb_obj_value(mrb->false_class);
case MRB_TT_TRUE:
return mrb_obj_value(mrb->true_class);
- case MRB_TT_VOIDP:
+ case MRB_TT_CPTR:
return mrb_obj_value(mrb->object_class);
case MRB_TT_SYMBOL:
case MRB_TT_FIXNUM:
@@ -939,6 +982,10 @@ mrb_singleton_class(mrb_state *mrb, mrb_value v)
}
obj = mrb_basic_ptr(v);
prepare_singleton_class(mrb, obj);
+ if (mrb->c && mrb->c->ci && mrb->c->ci->target_class) {
+ mrb_obj_iv_set(mrb, (struct RObject*)obj->c, mrb_intern_lit(mrb, "__outer__"),
+ mrb_obj_value(mrb->c->ci->target_class));
+ }
return mrb_obj_value(obj->c);
}
@@ -973,7 +1020,7 @@ mrb_method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
khash_t(mt) *h = c->mt;
if (h) {
- k = kh_get(mt, h, mid);
+ k = kh_get(mt, mrb, h, mid);
if (k != kh_end(h)) {
m = kh_value(h, k);
if (!m) break;
@@ -1003,10 +1050,19 @@ mrb_method_search(mrb_state *mrb, struct RClass* c, mrb_sym mid)
return m;
}
-void
-mrb_obj_call_init(mrb_state *mrb, mrb_value obj, int argc, mrb_value *argv)
+static mrb_value
+mrb_instance_alloc(mrb_state *mrb, mrb_value cv)
{
- mrb_funcall_argv(mrb, obj, mrb->init_sym, argc, argv);
+ struct RClass *c = mrb_class_ptr(cv);
+ struct RObject *o;
+ enum mrb_vtype ttype = MRB_INSTANCE_TT(c);
+
+ if (c->tt == MRB_TT_SCLASS)
+ mrb_raise(mrb, E_TYPE_ERROR, "can't create instance of singleton class");
+
+ if (ttype == 0) ttype = MRB_TT_OBJECT;
+ o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
+ return mrb_obj_value(o);
}
/*
@@ -1020,70 +1076,47 @@ mrb_obj_call_init(mrb_state *mrb, mrb_value obj, int argc, mrb_value *argv)
* an object is constructed using .new.
*
*/
-mrb_value
-mrb_class_new_instance(mrb_state *mrb, int argc, mrb_value *argv, struct RClass * klass)
-{
- mrb_value obj;
- struct RClass * c = (struct RClass*)mrb_obj_alloc(mrb, klass->tt, klass);
- c->super = klass;
- obj = mrb_obj_value(c);
- mrb_obj_call_init(mrb, obj, argc, argv);
- return obj;
-}
mrb_value
-mrb_class_new_instance_m(mrb_state *mrb, mrb_value klass)
+mrb_instance_new(mrb_state *mrb, mrb_value cv)
{
+ mrb_value obj, blk;
mrb_value *argv;
- mrb_value blk;
- struct RClass *k = mrb_class_ptr(klass);
- struct RClass *c;
int argc;
- mrb_value obj;
+ obj = mrb_instance_alloc(mrb, cv);
mrb_get_args(mrb, "*&", &argv, &argc, &blk);
- c = (struct RClass*)mrb_obj_alloc(mrb, k->tt, k);
- c->super = k;
- obj = mrb_obj_value(c);
- mrb_funcall_with_block(mrb, obj, mrb->init_sym, argc, argv, blk);
+ mrb_funcall_with_block(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv, blk);
return obj;
}
mrb_value
-mrb_instance_new(mrb_state *mrb, mrb_value cv)
+mrb_obj_new(mrb_state *mrb, struct RClass *c, int argc, const mrb_value *argv)
{
- struct RClass *c = mrb_class_ptr(cv);
- struct RObject *o;
- enum mrb_vtype ttype = MRB_INSTANCE_TT(c);
- mrb_value obj, blk;
- mrb_value *argv;
- int argc;
-
- if (c->tt == MRB_TT_SCLASS)
- mrb_raise(mrb, E_TYPE_ERROR, "can't create instance of singleton class");
+ mrb_value obj;
- if (ttype == 0) ttype = MRB_TT_OBJECT;
- o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
- obj = mrb_obj_value(o);
- mrb_get_args(mrb, "*&", &argv, &argc, &blk);
- mrb_funcall_with_block(mrb, obj, mrb->init_sym, argc, argv, blk);
+ obj = mrb_instance_alloc(mrb, mrb_obj_value(c));
+ mrb_funcall_argv(mrb, obj, mrb_intern_lit(mrb, "initialize"), argc, argv);
return obj;
}
-mrb_value
+static mrb_value
mrb_class_new_class(mrb_state *mrb, mrb_value cv)
{
- mrb_value super;
- struct RClass *new_class;
+ mrb_value super, blk;
+ mrb_value new_class;
- if (mrb_get_args(mrb, "|o", &super) == 0) {
+ if (mrb_get_args(mrb, "|C&", &super, &blk) == 0) {
super = mrb_obj_value(mrb->object_class);
}
- new_class = mrb_class_new(mrb, mrb_class_ptr(super));
- mrb_funcall(mrb, super, "inherited", 1, mrb_obj_value(new_class));
- return mrb_obj_value(new_class);
+ new_class = mrb_obj_value(mrb_class_new(mrb, mrb_class_ptr(super)));
+ if (!mrb_nil_p(blk)) {
+ mrb_funcall_with_block(mrb, new_class, mrb_intern_lit(mrb, "class_eval"), 0, NULL, blk);
+ }
+ mrb_funcall(mrb, super, "inherited", 1, new_class);
+ return new_class;
}
mrb_value
@@ -1151,28 +1184,34 @@ mrb_bob_missing(mrb_state *mrb, mrb_value mod)
mrb_sym name;
mrb_value *a;
int alen;
- mrb_value inspect;
+ mrb_sym inspect;
+ mrb_value repr;
mrb_get_args(mrb, "n*", &name, &a, &alen);
- if (mrb_respond_to(mrb,mod,mrb_intern2(mrb, "inspect",7))){
- inspect = mrb_funcall(mrb, mod, "inspect", 0);
- if (RSTRING_LEN(inspect) > 64) {
- inspect = mrb_any_to_s(mrb, mod);
+ inspect = mrb_intern_lit(mrb, "inspect");
+ if (mrb->c->ci > mrb->c->cibase && mrb->c->ci[-1].mid == inspect) {
+ /* method missing in inspect; avoid recursion */
+ repr = mrb_any_to_s(mrb, mod);
+ }
+ else if (mrb_respond_to(mrb, mod, inspect)) {
+ repr = mrb_funcall_argv(mrb, mod, inspect, 0, 0);
+ if (RSTRING_LEN(repr) > 64) {
+ repr = mrb_any_to_s(mrb, mod);
}
}
else {
- inspect = mrb_any_to_s(mrb, mod);
+ repr = mrb_any_to_s(mrb, mod);
}
mrb_raisef(mrb, E_NOMETHOD_ERROR, "undefined method '%S' for %S",
- mrb_sym2str(mrb, name), inspect);
+ mrb_sym2str(mrb, name), repr);
/* not reached */
return mrb_nil_value();
}
mrb_bool
-mrb_obj_respond_to(struct RClass* c, mrb_sym mid)
+mrb_obj_respond_to(mrb_state *mrb, struct RClass* c, mrb_sym mid)
{
khiter_t k;
@@ -1180,7 +1219,7 @@ mrb_obj_respond_to(struct RClass* c, mrb_sym mid)
khash_t(mt) *h = c->mt;
if (h) {
- k = kh_get(mt, h, mid);
+ k = kh_get(mt, mrb, h, mid);
if (k != kh_end(h)) {
if (kh_value(h, k)) {
return TRUE; /* method exists */
@@ -1198,7 +1237,7 @@ mrb_obj_respond_to(struct RClass* c, mrb_sym mid)
mrb_bool
mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid)
{
- return mrb_obj_respond_to(mrb_class(mrb, obj), mid);
+ return mrb_obj_respond_to(mrb, mrb_class(mrb, obj), mid);
}
mrb_value
@@ -1206,8 +1245,8 @@ mrb_class_path(mrb_state *mrb, struct RClass *c)
{
mrb_value path;
const char *name;
- size_t len;
- mrb_sym classpath = mrb_intern2(mrb, "__classpath__", 13);
+ mrb_int len;
+ mrb_sym classpath = mrb_intern_lit(mrb, "__classpath__");
path = mrb_obj_iv_get(mrb, (struct RObject*)c, classpath);
if (mrb_nil_p(path)) {
@@ -1218,7 +1257,7 @@ mrb_class_path(mrb_state *mrb, struct RClass *c)
}
else if (outer && outer != mrb->object_class) {
mrb_value base = mrb_class_path(mrb, outer);
- path = mrb_str_plus(mrb, base, mrb_str_new(mrb, "::", 2));
+ path = mrb_str_plus(mrb, base, mrb_str_new_lit(mrb, "::"));
name = mrb_sym2name_len(mrb, sym, &len);
mrb_str_concat(mrb, path, mrb_str_new(mrb, name, len));
}
@@ -1245,11 +1284,11 @@ mrb_class_name(mrb_state *mrb, struct RClass* c)
{
mrb_value path = mrb_class_path(mrb, c);
if (mrb_nil_p(path)) {
- path = mrb_str_new(mrb, "#<Class:", 8);
+ path = mrb_str_new_lit(mrb, "#<Class:");
mrb_str_concat(mrb, path, mrb_ptr_to_str(mrb, c));
- mrb_str_cat(mrb, path, ">", 1);
+ mrb_str_cat_lit(mrb, path, ">");
}
- return mrb_str_ptr(path)->ptr;
+ return RSTRING_PTR(path);
}
const char*
@@ -1368,9 +1407,9 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
mrb_value str;
if (mrb_type(klass) == MRB_TT_SCLASS) {
- mrb_value v = mrb_iv_get(mrb, klass, mrb_intern2(mrb, "__attached__", 12));
+ mrb_value v = mrb_iv_get(mrb, klass, mrb_intern_lit(mrb, "__attached__"));
- str = mrb_str_new(mrb, "#<Class:", 8);
+ str = mrb_str_new_lit(mrb, "#<Class:");
switch (mrb_type(v)) {
case MRB_TT_CLASS:
@@ -1382,7 +1421,7 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
mrb_str_append(mrb, str, mrb_any_to_s(mrb, v));
break;
}
- mrb_str_cat(mrb, str, ">", 1);
+ mrb_str_cat_lit(mrb, str, ">");
}
else {
struct RClass *c;
@@ -1395,20 +1434,20 @@ mrb_mod_to_s(mrb_state *mrb, mrb_value klass)
if (mrb_nil_p(path)) {
switch (mrb_type(klass)) {
case MRB_TT_CLASS:
- mrb_str_cat(mrb, str, "#<Class:", 8);
+ mrb_str_cat_lit(mrb, str, "#<Class:");
break;
case MRB_TT_MODULE:
- mrb_str_cat(mrb, str, "#<Module:", 9);
+ mrb_str_cat_lit(mrb, str, "#<Module:");
break;
default:
/* Shouldn't be happened? */
- mrb_str_cat(mrb, str, "#<??????:", 9);
+ mrb_str_cat_lit(mrb, str, "#<??????:");
break;
}
mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, c));
- mrb_str_cat(mrb, str, ">", 1);
+ mrb_str_cat_lit(mrb, str, ">");
}
else {
str = path;
@@ -1434,7 +1473,7 @@ undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a)
{
mrb_value m;
- if (!mrb_obj_respond_to(c, 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 {
@@ -1484,15 +1523,16 @@ mod_define_method(mrb_state *mrb, mrb_value self)
}
p = (struct RProc*)mrb_obj_alloc(mrb, MRB_TT_PROC, mrb->proc_class);
mrb_proc_copy(p, mrb_proc_ptr(blk));
+ p->flags |= MRB_PROC_STRICT;
mrb_define_method_raw(mrb, c, mid, p);
- return blk;
+ return mrb_symbol_value(mid);
}
static void
check_cv_name_sym(mrb_state *mrb, mrb_sym id)
{
const char *s;
- size_t len;
+ mrb_int len;
s = mrb_sym2name_len(mrb, id, &len);
if (len < 3 || !(s[0] == '@' && s[1] == '@')) {
@@ -1504,7 +1544,8 @@ static void
check_cv_name_str(mrb_state *mrb, mrb_value str)
{
const char *s = RSTRING_PTR(str);
- size_t const len = RSTRING_LEN(str);
+ mrb_int len = RSTRING_LEN(str);
+
if (len < 3 || !(s[0] == '@' && s[1] == '@')) {
mrb_name_error(mrb, mrb_intern_str(mrb, str), "`%S' is not allowed as a class variable name", str);
}
@@ -1704,7 +1745,7 @@ mrb_mod_method_defined(mrb_state *mrb, mrb_value mod)
id = get_sym_or_str_arg(mrb);
if (mrb_symbol_p(id)) {
- method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), mrb_symbol(id));
+ method_defined_p = mrb_obj_respond_to(mrb, mrb_class_ptr(mod), mrb_symbol(id));
}
else {
mrb_value sym = mrb_check_intern_str(mrb, id);
@@ -1712,7 +1753,7 @@ mrb_mod_method_defined(mrb_state *mrb, mrb_value mod)
method_defined_p = FALSE;
}
else {
- method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), mrb_symbol(sym));
+ method_defined_p = mrb_obj_respond_to(mrb, mrb_class_ptr(mod), mrb_symbol(sym));
}
}
return mrb_bool_value(method_defined_p);
@@ -1726,9 +1767,9 @@ remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid)
khiter_t k;
if (h) {
- k = kh_get(mt, h, mid);
+ k = kh_get(mt, mrb, h, mid);
if (k != kh_end(h)) {
- kh_del(mt, h, k);
+ kh_del(mt, mrb, h, k);
return;
}
}
@@ -1764,7 +1805,7 @@ static void
check_const_name_sym(mrb_state *mrb, mrb_sym id)
{
const char *s;
- size_t len;
+ mrb_int len;
s = mrb_sym2name_len(mrb, id, &len);
if (len < 1 || !ISUPPER(*s)) {
@@ -1843,6 +1884,18 @@ mrb_mod_remove_const(mrb_state *mrb, mrb_value mod)
return val;
}
+mrb_value
+mrb_mod_const_missing(mrb_state *mrb, mrb_value mod)
+{
+ mrb_sym sym;
+
+ mrb_get_args(mrb, "n", &sym);
+ mrb_name_error(mrb, sym, "uninitialized constant %S",
+ mrb_sym2str(mrb, sym));
+ /* not reached */
+ return mrb_nil_value();
+}
+
static mrb_value
mrb_mod_s_constants(mrb_state *mrb, mrb_value mod)
{
@@ -1869,7 +1922,6 @@ mrb_init_class(mrb_state *mrb)
struct RClass *obj; /* Object */
struct RClass *mod; /* Module */
struct RClass *cls; /* Class */
- //struct RClass *krn; /* Kernel */
/* boot class hierarchy */
bob = boot_defclass(mrb, 0);
@@ -1891,10 +1943,10 @@ mrb_init_class(mrb_state *mrb)
mrb_define_const(mrb, obj, "Class", mrb_obj_value(cls));
/* name each classes */
- mrb_name_class(mrb, bob, mrb_intern2(mrb, "BasicObject", 11)); /* 15.2.1 */
- mrb_name_class(mrb, obj, mrb_intern2(mrb, "Object", 6)); /* 15.2.1 */
- mrb_name_class(mrb, mod, mrb_intern2(mrb, "Module", 6)); /* 15.2.2 */
- mrb_name_class(mrb, cls, mrb_intern2(mrb, "Class", 5)); /* 15.2.3 */
+ name_class(mrb, bob, mrb_intern_lit(mrb, "BasicObject"));
+ name_class(mrb, obj, mrb_intern_lit(mrb, "Object")); /* 15.2.1 */
+ name_class(mrb, mod, mrb_intern_lit(mrb, "Module")); /* 15.2.2 */
+ name_class(mrb, cls, mrb_intern_lit(mrb, "Class")); /* 15.2.3 */
MRB_SET_INSTANCE_TT(cls, MRB_TT_CLASS);
mrb_define_method(mrb, bob, "initialize", mrb_bob_init, MRB_ARGS_NONE());
@@ -1936,6 +1988,7 @@ mrb_init_class(mrb_state *mrb)
mrb_define_method(mrb, mod, "const_set", mrb_mod_const_set, MRB_ARGS_REQ(2)); /* 15.2.2.4.23 */
mrb_define_method(mrb, mod, "constants", mrb_mod_constants, MRB_ARGS_NONE()); /* 15.2.2.4.24 */
mrb_define_method(mrb, mod, "remove_const", mrb_mod_remove_const, MRB_ARGS_REQ(1)); /* 15.2.2.4.40 */
+ mrb_define_method(mrb, mod, "const_missing", mrb_mod_const_missing, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mod, "define_method", mod_define_method, MRB_ARGS_REQ(1));
mrb_define_method(mrb, mod, "class_variables", mrb_mod_class_variables, MRB_ARGS_NONE()); /* 15.2.2.4.19 */
mrb_define_method(mrb, mod, "===", mrb_mod_eqq, MRB_ARGS_REQ(1));