summaryrefslogtreecommitdiffhomepage
path: root/src/kernel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel.c')
-rw-r--r--src/kernel.c205
1 files changed, 133 insertions, 72 deletions
diff --git a/src/kernel.c b/src/kernel.c
index 4b426c6b4..d8a8e371f 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -10,29 +10,29 @@
#include "mruby/proc.h"
#include "mruby/string.h"
#include "mruby/variable.h"
-#include "error.h"
+#include "mruby/error.h"
typedef enum {
- NOEX_PUBLIC = 0x00,
- NOEX_NOSUPER = 0x01,
- NOEX_PRIVATE = 0x02,
- NOEX_PROTECTED = 0x04,
- NOEX_MASK = 0x06,
- NOEX_BASIC = 0x08,
- NOEX_UNDEF = NOEX_NOSUPER,
- NOEX_MODFUNC = 0x12,
- NOEX_SUPER = 0x20,
- NOEX_VCALL = 0x40,
- NOEX_RESPONDS = 0x80
+ NOEX_PUBLIC = 0x00,
+ NOEX_NOSUPER = 0x01,
+ NOEX_PRIVATE = 0x02,
+ NOEX_PROTECTED = 0x04,
+ NOEX_MASK = 0x06,
+ NOEX_BASIC = 0x08,
+ NOEX_UNDEF = NOEX_NOSUPER,
+ NOEX_MODFUNC = 0x12,
+ NOEX_SUPER = 0x20,
+ NOEX_VCALL = 0x40,
+ NOEX_RESPONDS = 0x80
} mrb_method_flag_t;
mrb_bool
mrb_obj_basic_to_s_p(mrb_state *mrb, mrb_value obj)
{
- struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern2(mrb, "to_s", 4));
- if (me && MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s))
- return TRUE;
- return FALSE;
+ struct RProc *me = mrb_method_search(mrb, mrb_class(mrb, obj), mrb_intern_lit(mrb, "to_s"));
+ if (me && MRB_PROC_CFUNC_P(me) && (me->body.func == mrb_any_to_s))
+ return TRUE;
+ return FALSE;
}
/* 15.3.1.3.17 */
@@ -157,36 +157,6 @@ mrb_obj_id_m(mrb_state *mrb, mrb_value self)
return mrb_fixnum_value(mrb_obj_id(self));
}
-/* 15.3.1.3.4 */
-/* 15.3.1.3.44 */
-/*
- * call-seq:
- * obj.send(symbol [, args...]) -> obj
- * obj.__send__(symbol [, args...]) -> obj
- *
- * Invokes the method identified by _symbol_, passing it any
- * arguments specified. You can use <code>__send__</code> if the name
- * +send+ clashes with an existing method in _obj_.
- *
- * class Klass
- * def hello(*args)
- * "Hello " + args.join(' ')
- * end
- * end
- * k = Klass.new
- * k.send :hello, "gentle", "readers" #=> "Hello gentle readers"
- */
-static mrb_value
-mrb_f_send(mrb_state *mrb, mrb_value self)
-{
- mrb_sym name;
- mrb_value block, *argv;
- int argc;
-
- mrb_get_args(mrb, "n*&", &name, &argv, &argc, &block);
- return mrb_funcall_with_block(mrb,self, name, argc, argv, block);
-}
-
/* 15.3.1.2.2 */
/* 15.3.1.2.5 */
/* 15.3.1.3.6 */
@@ -218,7 +188,7 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
mrb_value *bp;
mrb_bool given_p;
- bp = mrb->c->stbase + ci->stackidx + 1;
+ bp = ci->stackent + 1;
ci--;
if (ci <= mrb->c->cibase) {
given_p = 0;
@@ -240,6 +210,26 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
return mrb_bool_value(given_p);
}
+/*
+ * call-seq:
+ * __method__ -> symbol
+ *
+ * Returns the name at the definition of the current method as a
+ * Symbol.
+ * If called outside of a method, it returns <code>nil</code>.
+ *
+ */
+static mrb_value
+mrb_f_method(mrb_state *mrb, mrb_value self)
+{
+ mrb_callinfo *ci = mrb->c->ci;
+ ci--;
+ if (ci->mid)
+ return mrb_symbol_value(ci->mid);
+ else
+ return mrb_nil_value();
+}
+
/* 15.3.1.3.7 */
/*
* call-seq:
@@ -280,7 +270,7 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
clone->super = klass->super;
if (klass->iv) {
mrb_iv_copy(mrb, mrb_obj_value(clone), mrb_obj_value(klass));
- mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern2(mrb, "__attached__", 12), obj);
+ mrb_obj_iv_set(mrb, (struct RObject*)clone, mrb_intern_lit(mrb, "__attached__"), obj);
}
if (klass->mt) {
clone->mt = kh_copy(mt, mrb, klass->mt);
@@ -294,12 +284,23 @@ mrb_singleton_class_clone(mrb_state *mrb, mrb_value obj)
}
static void
+copy_class(mrb_state *mrb, mrb_value dst, mrb_value src)
+{
+ struct RClass *dc = mrb_class_ptr(dst);
+ struct RClass *sc = mrb_class_ptr(src);
+ dc->mt = kh_copy(mt, mrb, sc->mt);
+ dc->super = sc->super;
+}
+
+static void
init_copy(mrb_state *mrb, mrb_value dest, mrb_value obj)
{
- switch (mrb_type(obj)) {
- case MRB_TT_OBJECT:
+ switch (mrb_type(obj)) {
case MRB_TT_CLASS:
case MRB_TT_MODULE:
+ copy_class(mrb, dest, obj);
+ /* fall through */
+ case MRB_TT_OBJECT:
case MRB_TT_SCLASS:
case MRB_TT_HASH:
case MRB_TT_DATA:
@@ -474,8 +475,6 @@ mrb_obj_init_copy(mrb_state *mrb, mrb_value self)
return self;
}
-mrb_value mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_value self, struct RClass *c);
-
/* 15.3.1.3.18 */
/*
* call-seq:
@@ -518,7 +517,7 @@ mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
c = mrb_class_ptr(cv);
break;
}
- return mrb_yield_internal(mrb, b, 0, 0, self, c);
+ return mrb_yield_with_class(mrb, b, 0, 0, self, c);
}
mrb_bool
@@ -542,14 +541,14 @@ obj_is_instance_of(mrb_state *mrb, mrb_value self)
mrb_value arg;
mrb_bool instance_of_p;
- mrb_get_args(mrb, "o", &arg);
+ mrb_get_args(mrb, "C", &arg);
instance_of_p = mrb_obj_is_instance_of(mrb, self, mrb_class_ptr(arg));
return mrb_bool_value(instance_of_p);
}
static void
-valid_iv_name(mrb_state *mrb, mrb_sym iv_name_id, const char* s, size_t len)
+valid_iv_name(mrb_state *mrb, mrb_sym iv_name_id, const char* s, mrb_int len)
{
if (len < 2 || !(s[0] == '@' && s[1] != '@')) {
mrb_name_error(mrb, iv_name_id, "`%S' is not allowed as an instance variable name", mrb_sym2str(mrb, iv_name_id));
@@ -560,7 +559,7 @@ static void
check_iv_name(mrb_state *mrb, mrb_sym iv_name_id)
{
const char *s;
- size_t len;
+ mrb_int len;
s = mrb_sym2name_len(mrb, iv_name_id, &len);
valid_iv_name(mrb, iv_name_id, s, len);
@@ -574,8 +573,10 @@ get_valid_iv_sym(mrb_state *mrb, mrb_value iv_name)
mrb_assert(mrb_symbol_p(iv_name) || mrb_string_p(iv_name));
if (mrb_string_p(iv_name)) {
- iv_name_id = mrb_intern_cstr(mrb, RSTRING_PTR(iv_name));
- valid_iv_name(mrb, iv_name_id, RSTRING_PTR(iv_name), RSTRING_LEN(iv_name));
+ char *p = RSTRING_PTR(iv_name);
+ mrb_int l = RSTRING_LEN(iv_name);
+ iv_name_id = mrb_intern(mrb, p, l);
+ valid_iv_name(mrb, iv_name_id, p, l);
}
else {
iv_name_id = mrb_symbol(iv_name);
@@ -715,14 +716,17 @@ mrb_obj_is_kind_of_m(mrb_state *mrb, mrb_value self)
mrb_value arg;
mrb_bool kind_of_p;
- mrb_get_args(mrb, "o", &arg);
+ mrb_get_args(mrb, "C", &arg);
kind_of_p = mrb_obj_is_kind_of(mrb, self, mrb_class_ptr(arg));
return mrb_bool_value(kind_of_p);
}
+KHASH_DECLARE(st, mrb_sym, char, FALSE)
+KHASH_DEFINE(st, mrb_sym, char, FALSE, kh_int_hash_func, kh_int_hash_equal)
+
static void
-method_entry_loop(mrb_state *mrb, struct RClass* klass, mrb_value ary)
+method_entry_loop(mrb_state *mrb, struct RClass* klass, khash_t(st)* set)
{
khint_t i;
@@ -730,21 +734,22 @@ method_entry_loop(mrb_state *mrb, struct RClass* klass, mrb_value ary)
if (!h) return;
for (i=0;i<kh_end(h);i++) {
if (kh_exist(h, i)) {
- mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(h,i)));
+ kh_put(st, mrb, set, kh_key(h,i));
}
}
}
mrb_value
-class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* klass, int obj)
+mrb_class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* klass, int obj)
{
+ khint_t i;
mrb_value ary;
struct RClass* oldklass;
+ khash_t(st)* set = kh_init(st, mrb);
- ary = mrb_ary_new(mrb);
oldklass = 0;
while (klass && (klass != oldklass)) {
- method_entry_loop(mrb, klass, ary);
+ method_entry_loop(mrb, klass, set);
if ((klass->tt == MRB_TT_ICLASS) ||
(klass->tt == MRB_TT_SCLASS)) {
}
@@ -755,28 +760,46 @@ class_instance_method_list(mrb_state *mrb, mrb_bool recur, struct RClass* klass,
klass = klass->super;
}
+ ary = mrb_ary_new(mrb);
+ for (i=0;i<kh_end(set);i++) {
+ if (kh_exist(set, i)) {
+ mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set,i)));
+ }
+ }
+ kh_destroy(st, mrb, set);
+
return ary;
}
mrb_value
mrb_obj_singleton_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj)
{
+ khint_t i;
mrb_value ary;
struct RClass* klass;
+ khash_t(st)* set = kh_init(st, mrb);
klass = mrb_class(mrb, obj);
- ary = mrb_ary_new(mrb);
+
if (klass && (klass->tt == MRB_TT_SCLASS)) {
- method_entry_loop(mrb, klass, ary);
+ method_entry_loop(mrb, klass, set);
klass = klass->super;
}
if (recur) {
while (klass && ((klass->tt == MRB_TT_SCLASS) || (klass->tt == MRB_TT_ICLASS))) {
- method_entry_loop(mrb, klass, ary);
+ method_entry_loop(mrb, klass, set);
klass = klass->super;
}
}
+ ary = mrb_ary_new(mrb);
+ for (i=0;i<kh_end(set);i++) {
+ if (kh_exist(set, i)) {
+ mrb_ary_push(mrb, ary, mrb_symbol_value(kh_key(set,i)));
+ }
+ }
+ kh_destroy(st, mrb, set);
+
return ary;
}
@@ -784,7 +807,7 @@ mrb_value
mrb_obj_methods(mrb_state *mrb, mrb_bool recur, mrb_value obj, mrb_method_flag_t flag)
{
if (recur)
- return class_instance_method_list(mrb, recur, mrb_class(mrb, obj), 0);
+ return mrb_class_instance_method_list(mrb, recur, mrb_class(mrb, obj), 0);
else
return mrb_obj_singleton_methods(mrb, recur, obj);
}
@@ -922,7 +945,7 @@ mrb_f_raise(mrb_state *mrb, mrb_value self)
/* fall through */
default:
exc = mrb_make_exception(mrb, argc, a);
- mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(mrb, mrb->c->ci->pc));
+ mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern_lit(mrb, "lastpc"), mrb_cptr_value(mrb, mrb->c->ci->pc));
mrb_exc_raise(mrb, exc);
break;
}
@@ -987,7 +1010,7 @@ basic_obj_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym id, int pub)
* If the method is not defined, <code>respond_to_missing?</code>
* method is called and the result is returned.
*/
-mrb_value
+static mrb_value
obj_respond_to(mrb_state *mrb, mrb_value self)
{
mrb_value *argv;
@@ -1027,7 +1050,7 @@ obj_respond_to(mrb_state *mrb, mrb_value self)
}
if (!respond_to_p) {
- rtm_id = mrb_intern2(mrb, "respond_to_missing?", 19);
+ rtm_id = mrb_intern_lit(mrb, "respond_to_missing?");
if (basic_obj_respond_to(mrb, self, rtm_id, !mrb_test(priv))) {
return mrb_funcall_argv(mrb, self, rtm_id, argc, argv);
}
@@ -1076,6 +1099,41 @@ mrb_obj_singleton_methods_m(mrb_state *mrb, mrb_value self)
return mrb_obj_singleton_methods(mrb, recur, self);
}
+static mrb_value
+mod_define_singleton_method(mrb_state *mrb, mrb_value self)
+{
+ struct RProc *p;
+ mrb_sym mid;
+ mrb_value blk = mrb_nil_value();
+
+ mrb_get_args(mrb, "n&", &mid, &blk);
+ if (mrb_nil_p(blk)) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
+ }
+ 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, mrb_class_ptr(mrb_singleton_class(mrb, self)), mid, p);
+ return mrb_symbol_value(mid);
+}
+
+static mrb_value
+mrb_obj_ceqq(mrb_state *mrb, mrb_value self)
+{
+ mrb_value v;
+ mrb_int i, len;
+ mrb_sym eqq = mrb_intern_lit(mrb, "===");
+ mrb_value ary = mrb_ary_splat(mrb, self);
+
+ mrb_get_args(mrb, "o", &v);
+ len = RARRAY_LEN(ary);
+ for (i=0; i<len; i++) {
+ mrb_value c = mrb_funcall_argv(mrb, mrb_ary_entry(ary, i), eqq, 1, &v);
+ if (mrb_test(c)) return mrb_true_value();
+ }
+ return mrb_false_value();
+}
+
void
mrb_init_kernel(mrb_state *mrb)
{
@@ -1095,6 +1153,7 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method(mrb, krn, "===", mrb_equal_m, MRB_ARGS_REQ(1)); /* 15.3.1.3.2 */
mrb_define_method(mrb, krn, "__id__", mrb_obj_id_m, MRB_ARGS_NONE()); /* 15.3.1.3.3 */
mrb_define_method(mrb, krn, "__send__", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.4 */
+ mrb_define_method(mrb, krn, "__method__", mrb_f_method, MRB_ARGS_NONE());
mrb_define_method(mrb, krn, "block_given?", mrb_f_block_given_p_m, MRB_ARGS_NONE()); /* 15.3.1.3.6 */
mrb_define_method(mrb, krn, "class", mrb_obj_class_m, MRB_ARGS_NONE()); /* 15.3.1.3.7 */
mrb_define_method(mrb, krn, "clone", mrb_obj_clone, MRB_ARGS_NONE()); /* 15.3.1.3.8 */
@@ -1126,8 +1185,10 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method(mrb, krn, "respond_to?", obj_respond_to, MRB_ARGS_ANY()); /* 15.3.1.3.43 */
mrb_define_method(mrb, krn, "send", mrb_f_send, MRB_ARGS_ANY()); /* 15.3.1.3.44 */
mrb_define_method(mrb, krn, "singleton_methods", mrb_obj_singleton_methods_m, MRB_ARGS_OPT(1)); /* 15.3.1.3.45 */
+ mrb_define_method(mrb, krn, "define_singleton_method", mod_define_singleton_method, MRB_ARGS_ANY());
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_include_module(mrb, mrb->object_class, mrb->kernel_module);
- mrb_alias_method(mrb, mrb->module_class, mrb_intern2(mrb, "dup", 3), mrb_intern2(mrb, "clone", 5));
+ mrb_alias_method(mrb, mrb->module_class, mrb_intern_lit(mrb, "dup"), mrb_intern_lit(mrb, "clone"));
}