aboutsummaryrefslogtreecommitdiffstats
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authorshugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-08-02 11:34:19 +0000
committershugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-08-02 11:34:19 +0000
commit19ddfc2483bb82cfb241a58d4b25956f7b79d1ad (patch)
treec5eecb286e12abe5d5201d4fe2c6bee9efdf5a31 /vm_insnhelper.c
parent319088e9c7ae9836efd242592ea80c9794a45002 (diff)
downloadruby-19ddfc2483bb82cfb241a58d4b25956f7b79d1ad.tar.gz
* eval.c (rb_mod_using): new method Module#using. [experimental]
* eval.c (rb_mod_refine): new method Module#refine. [experimental] * eval.c (f_using): new method Kernel#using. [experimental] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36596 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c80
1 files changed, 70 insertions, 10 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 8e24a73604..b06fb55f02 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1128,13 +1128,13 @@ vm_get_cref0(const rb_iseq_t *iseq, const VALUE *ep)
}
}
-static NODE *
-vm_get_cref(const rb_iseq_t *iseq, const VALUE *ep)
+NODE *
+rb_vm_get_cref(const rb_iseq_t *iseq, const VALUE *ep)
{
NODE *cref = vm_get_cref0(iseq, ep);
if (cref == 0) {
- rb_bug("vm_get_cref: unreachable");
+ rb_bug("rb_vm_get_cref: unreachable");
}
return cref;
}
@@ -1143,7 +1143,8 @@ static NODE *
vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr)
{
rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
- NODE *cref = NEW_BLOCK(klass);
+ NODE *cref = NEW_CREF(klass);
+ cref->nd_omod = Qnil;
cref->nd_visi = noex;
if (blockptr) {
@@ -1152,6 +1153,11 @@ vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr)
else if (cfp) {
cref->nd_next = vm_get_cref0(cfp->iseq, cfp->ep);
}
+ /* TODO: why cref->nd_next is 1? */
+ if (cref->nd_next && cref->nd_next != (void *) 1 &&
+ !NIL_P(cref->nd_next->nd_omod)) {
+ COPY_CREF_OMOD(cref, cref->nd_next);
+ }
return cref;
}
@@ -1159,7 +1165,7 @@ vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr)
static inline VALUE
vm_get_cbase(const rb_iseq_t *iseq, const VALUE *ep)
{
- NODE *cref = vm_get_cref(iseq, ep);
+ NODE *cref = rb_vm_get_cref(iseq, ep);
VALUE klass = Qundef;
while (cref) {
@@ -1175,7 +1181,7 @@ vm_get_cbase(const rb_iseq_t *iseq, const VALUE *ep)
static inline VALUE
vm_get_const_base(const rb_iseq_t *iseq, const VALUE *ep)
{
- NODE *cref = vm_get_cref(iseq, ep);
+ NODE *cref = rb_vm_get_cref(iseq, ep);
VALUE klass = Qundef;
while (cref) {
@@ -1201,6 +1207,20 @@ vm_check_if_namespace(VALUE klass)
}
static inline VALUE
+vm_get_iclass(rb_control_frame_t *cfp, VALUE klass)
+{
+ if (TYPE(klass) == T_MODULE &&
+ FL_TEST(klass, RMODULE_IS_OVERLAYED) &&
+ TYPE(cfp->klass) == T_ICLASS &&
+ RBASIC(cfp->klass)->klass == klass) {
+ return cfp->klass;
+ }
+ else {
+ return klass;
+ }
+}
+
+static inline VALUE
vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
VALUE orig_klass, ID id, int is_defined)
{
@@ -1208,7 +1228,7 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
if (orig_klass == Qnil) {
/* in current lexical scope */
- const NODE *root_cref = vm_get_cref(iseq, th->cfp->ep);
+ const NODE *root_cref = rb_vm_get_cref(iseq, th->cfp->ep);
const NODE *cref;
VALUE klass = orig_klass;
@@ -1254,7 +1274,7 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
/* search self */
if (root_cref && !NIL_P(root_cref->nd_clss)) {
- klass = root_cref->nd_clss;
+ klass = vm_get_iclass(th->cfp, root_cref->nd_clss);
}
else {
klass = CLASS_OF(th->cfp->self);
@@ -1279,7 +1299,7 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
}
static inline VALUE
-vm_get_cvar_base(NODE *cref)
+vm_get_cvar_base(NODE *cref, rb_control_frame_t *cfp)
{
VALUE klass;
@@ -1296,7 +1316,7 @@ vm_get_cvar_base(NODE *cref)
rb_warn("class variable access from toplevel");
}
- klass = cref->nd_clss;
+ klass = vm_get_iclass(cfp, cref->nd_clss);
if (NIL_P(klass)) {
rb_raise(rb_eTypeError, "no class variables available");
@@ -1805,3 +1825,43 @@ opt_eq_func(VALUE recv, VALUE obj, IC ic)
return Qundef;
}
+void rb_using_module(NODE *cref, VALUE module);
+
+static int
+vm_using_module_i(VALUE module, VALUE value, VALUE arg)
+{
+ NODE *cref = (NODE *) arg;
+
+ rb_using_module(cref, module);
+ return ST_CONTINUE;
+}
+
+static void
+rb_vm_using_modules(NODE *cref, VALUE klass)
+{
+ ID id_using_modules;
+ VALUE using_modules;
+
+ CONST_ID(id_using_modules, "__using_modules__");
+ using_modules = rb_attr_get(klass, id_using_modules);
+ switch (TYPE(klass)) {
+ case T_CLASS:
+ if (NIL_P(using_modules)) {
+ VALUE super = rb_class_real(RCLASS_SUPER(klass));
+ using_modules = rb_attr_get(super, id_using_modules);
+ if (!NIL_P(using_modules)) {
+ using_modules = rb_hash_dup(using_modules);
+ rb_ivar_set(klass, id_using_modules, using_modules);
+ }
+ }
+ break;
+ case T_MODULE:
+ rb_using_module(cref, klass);
+ break;
+ }
+ if (!NIL_P(using_modules)) {
+ rb_hash_foreach(using_modules, vm_using_module_i,
+ (VALUE) cref);
+ }
+}
+