summaryrefslogtreecommitdiffhomepage
path: root/src/variable.c
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-08-01 15:57:32 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2017-08-01 15:57:32 +0900
commit3f6a098626d95ef59f566dad4afbef83249e9334 (patch)
tree0bc3d741f49e152100f9276e72af08b475a4a745 /src/variable.c
parent9e10afe1d0ee1fb751182e42044e891b4b13f9a4 (diff)
downloadmruby-3f6a098626d95ef59f566dad4afbef83249e9334.tar.gz
mruby-3f6a098626d95ef59f566dad4afbef83249e9334.zip
Reimplement constant look-up rule to follow lexical scoping.
This update fix CRuby scoping incompatibility; close #600; close #3200
Diffstat (limited to 'src/variable.c')
-rw-r--r--src/variable.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/src/variable.c b/src/variable.c
index 86ac32e61..9f4b2e728 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -833,31 +833,35 @@ mrb_value
mrb_vm_const_get(mrb_state *mrb, mrb_sym sym)
{
struct RClass *c = mrb->c->ci->proc->target_class;
+ struct RClass *c2;
+ mrb_value v;
+ struct RProc *proc;
if (!c) c = mrb->c->ci->target_class;
- if (c) {
- struct RClass *c2;
- mrb_value v;
+ mrb_assert(c != NULL);
- if (c->iv && iv_get(mrb, c->iv, sym, &v)) {
- return v;
- }
- c2 = c;
- while (c2 && c2->tt == MRB_TT_SCLASS) {
- mrb_value klass;
- klass = mrb_obj_iv_get(mrb, (struct RObject *)c2,
- mrb_intern_lit(mrb, "__attached__"));
- c2 = mrb_class_ptr(klass);
- }
- if (c2->tt == MRB_TT_CLASS || c2->tt == MRB_TT_MODULE) c = c2;
- c2 = c;
- for (;;) {
- c2 = mrb_class_outer_module(mrb, c2);
- if (!c2) break;
+ if (c->iv && iv_get(mrb, c->iv, sym, &v)) {
+ return v;
+ }
+ c2 = c;
+ while (c2 && c2->tt == MRB_TT_SCLASS) {
+ mrb_value klass;
+ klass = mrb_obj_iv_get(mrb, (struct RObject *)c2,
+ mrb_intern_lit(mrb, "__attached__"));
+ c2 = mrb_class_ptr(klass);
+ }
+ if (c2->tt == MRB_TT_CLASS || c2->tt == MRB_TT_MODULE) c = c2;
+ mrb_assert(!MRB_PROC_CFUNC_P(mrb->c->ci->proc));
+ proc = mrb->c->ci->proc->body.irep->outer;
+ while (proc) {
+ mrb_assert(!MRB_PROC_CFUNC_P(proc));
+ if (MRB_PROC_CLASS_P(proc) && proc->target_class) {
+ c2 = proc->target_class;
if (c2->iv && iv_get(mrb, c2->iv, sym, &v)) {
return v;
}
}
+ proc = proc->body.irep->outer;
}
return const_get(mrb, c, sym);
}