summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-metaprog/src
diff options
context:
space:
mode:
Diffstat (limited to 'mrbgems/mruby-metaprog/src')
-rw-r--r--mrbgems/mruby-metaprog/src/metaprog.c96
1 files changed, 50 insertions, 46 deletions
diff --git a/mrbgems/mruby-metaprog/src/metaprog.c b/mrbgems/mruby-metaprog/src/metaprog.c
index 6c0dc5ad3..b421226f9 100644
--- a/mrbgems/mruby-metaprog/src/metaprog.c
+++ b/mrbgems/mruby-metaprog/src/metaprog.c
@@ -132,8 +132,8 @@ mrb_obj_ivar_set(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_local_variables(mrb_state *mrb, mrb_value self)
{
- struct RProc *proc;
- mrb_irep *irep;
+ const struct RProc *proc;
+ const mrb_irep *irep;
mrb_value vars;
size_t i;
@@ -148,8 +148,8 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
irep = proc->body.irep;
if (irep->lv) {
for (i = 0; i + 1 < irep->nlocals; ++i) {
- if (irep->lv[i].name) {
- mrb_sym sym = irep->lv[i].name;
+ if (irep->lv[i]) {
+ mrb_sym sym = irep->lv[i];
const char *name = mrb_sym_name(mrb, sym);
switch (name[0]) {
case '*': case '&':
@@ -168,29 +168,50 @@ mrb_local_variables(mrb_state *mrb, mrb_value self)
return mrb_hash_keys(mrb, vars);
}
-KHASH_DECLARE(st, mrb_sym, char, FALSE)
+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, khash_t(st) *set, khash_t(st) *undef)
+union mt_ptr {
+ struct RProc *proc;
+ mrb_func_t func;
+};
+
+struct mt_elem {
+ union mt_ptr ptr;
+ size_t func_p:1;
+ mrb_sym key:sizeof(mrb_sym)*8-1;
+};
+
+struct mt_set {
+ khash_t(st) *set;
+ khash_t(st) *undef;
+};
+
+static int
+method_entry_i(mrb_state *mrb, mrb_sym mid, struct mt_elem *e, void *p)
{
- khint_t i;
+ struct mt_set *s = (struct mt_set*)p;
- khash_t(mt) *h = klass->mt;
- if (!h || kh_size(h) == 0) return;
- for (i=0;i<kh_end(h);i++) {
- if (kh_exist(h, i)) {
- mrb_method_t m = kh_value(h, i);
- if (MRB_METHOD_UNDEF_P(m)) {
- if (undef) {
- kh_put(st, mrb, undef, kh_key(h, i));
- }
- }
- else if (undef == NULL ||
- kh_get(st, mrb, undef, kh_key(h, i)) == kh_end(undef)) {
- kh_put(st, mrb, set, kh_key(h, i));
- }
+ if (e->ptr.proc == 0) {
+ if (s->undef) {
+ kh_put(st, mrb, s->undef, mid);
}
}
+ else if (s->undef == NULL ||
+ kh_get(st, mrb, s->undef, mid) == kh_end(s->undef)) {
+ kh_put(st, mrb, s->set, mid);
+ }
+ return 0;
+}
+
+static void
+method_entry_loop(mrb_state *mrb, struct RClass *klass, khash_t(st) *set, khash_t(st) *undef)
+{
+ struct mt_set s;
+
+ s.set = set;
+ s.undef = undef;
+ mrb_mt_foreach(mrb, klass, method_entry_i, (void*)&s);
}
static mrb_value
@@ -608,28 +629,6 @@ mrb_mod_instance_methods(mrb_state *mrb, mrb_value mod)
return mrb_class_instance_method_list(mrb, recur, c, 0);
}
-static void
-remove_method(mrb_state *mrb, mrb_value mod, mrb_sym mid)
-{
- struct RClass *c = mrb_class_ptr(mod);
- khash_t(mt) *h;
- khiter_t k;
-
- MRB_CLASS_ORIGIN(c);
- h = c->mt;
-
- if (h) {
- k = kh_get(mt, mrb, h, mid);
- if (k != kh_end(h)) {
- kh_del(mt, mrb, h, k);
- mrb_funcall(mrb, mod, "method_removed", 1, mrb_symbol_value(mid));
- return;
- }
- }
-
- mrb_name_error(mrb, mid, "method '%n' not defined in %v", mid, mod);
-}
-
/* 15.2.2.4.41 */
/*
* call-seq:
@@ -644,11 +643,13 @@ mrb_mod_remove_method(mrb_state *mrb, mrb_value mod)
{
mrb_int argc;
mrb_value *argv;
+ struct RClass *c = mrb_class_ptr(mod);
mrb_get_args(mrb, "*", &argv, &argc);
mrb_check_frozen(mrb, mrb_obj_ptr(mod));
while (argc--) {
- remove_method(mrb, mod, mrb_obj_to_sym(mrb, *argv));
+ mrb_remove_method(mrb, c, mrb_obj_to_sym(mrb, *argv));
+ mrb_funcall_id(mrb, mod, MRB_SYM(method_removed), 1, *argv);
argv++;
}
return mod;
@@ -664,7 +665,7 @@ mrb_mod_s_constants(mrb_state *mrb, mrb_value mod)
static mrb_value
mrb_mod_s_nesting(mrb_state *mrb, mrb_value mod)
{
- struct RProc *proc;
+ const struct RProc *proc;
mrb_value ary;
struct RClass *c = NULL;
@@ -684,6 +685,9 @@ mrb_mod_s_nesting(mrb_state *mrb, mrb_value mod)
return ary;
}
+/* implementation of #send method */
+mrb_value mrb_f_send(mrb_state *mrb, mrb_value self);
+
void
mrb_mruby_metaprog_gem_init(mrb_state* mrb)
{