зеркало из https://github.com/github/ruby.git
* compile.c (compile_cpath, iseq_compile_each): reverted
constant/class variable lookup in instance_eval etc. to the behavior of 1.8. * eval.c (rb_mod_nesting): ditto. * insns.def (putspecialobject, defineclass): ditto. * node.h (NODE_FL_CREF_PUSHED_BY_EVAL): ditto. * vm_core.h (VM_SPECIAL_OBJECT_CONST_BASE): ditto. * vm_eval.c (yield_under, eval_under): ditto. * vm_insnhelper.c (vm_cref_push, vm_get_const_base, vm_get_ev_const, vm_get_cvar_base): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25984 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
9998481d4e
Коммит
7dbfe89630
19
ChangeLog
19
ChangeLog
|
@ -1,3 +1,22 @@
|
|||
Fri Dec 4 03:10:38 2009 Shugo Maeda <shugo@ruby-lang.org>
|
||||
|
||||
* compile.c (compile_cpath, iseq_compile_each): reverted
|
||||
constant/class variable lookup in instance_eval etc. to the
|
||||
behavior of 1.8.
|
||||
|
||||
* eval.c (rb_mod_nesting): ditto.
|
||||
|
||||
* insns.def (putspecialobject, defineclass): ditto.
|
||||
|
||||
* node.h (NODE_FL_CREF_PUSHED_BY_EVAL): ditto.
|
||||
|
||||
* vm_core.h (VM_SPECIAL_OBJECT_CONST_BASE): ditto.
|
||||
|
||||
* vm_eval.c (yield_under, eval_under): ditto.
|
||||
|
||||
* vm_insnhelper.c (vm_cref_push, vm_get_const_base,
|
||||
vm_get_ev_const, vm_get_cvar_base): ditto.
|
||||
|
||||
Thu Dec 3 20:27:27 2009 Martin Duerst <duerst@it.aoyama.ac.jp>
|
||||
|
||||
* enc/trans/gb18030-tbl.rb: Fix omission of C1 region in code table
|
||||
|
|
|
@ -2549,7 +2549,8 @@ compile_cpath(LINK_ANCHOR *ret, rb_iseq_t *iseq, NODE *cpath)
|
|||
}
|
||||
else {
|
||||
/* class at cbase Foo */
|
||||
ADD_INSN1(ret, nd_line(cpath), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
|
||||
ADD_INSN1(ret, nd_line(cpath), putspecialobject,
|
||||
INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
|
||||
return Qtrue;
|
||||
}
|
||||
}
|
||||
|
@ -3710,7 +3711,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||
}
|
||||
|
||||
if (node->nd_vid) {
|
||||
ADD_INSN1(ret, nd_line(node), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
|
||||
ADD_INSN1(ret, nd_line(node), putspecialobject,
|
||||
INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
|
||||
ADD_INSN1(ret, nd_line(node), setconstant, ID2SYM(node->nd_vid));
|
||||
}
|
||||
else {
|
||||
|
|
3
eval.c
3
eval.c
|
@ -274,7 +274,8 @@ rb_mod_nesting(void)
|
|||
|
||||
while (cref && cref->nd_next) {
|
||||
VALUE klass = cref->nd_clss;
|
||||
if (!NIL_P(klass)) {
|
||||
if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
|
||||
!NIL_P(klass)) {
|
||||
rb_ary_push(ary, klass);
|
||||
}
|
||||
cref = cref->nd_next;
|
||||
|
|
|
@ -343,6 +343,9 @@ putspecialobject
|
|||
case VM_SPECIAL_OBJECT_CBASE:
|
||||
val = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||
break;
|
||||
case VM_SPECIAL_OBJECT_CONST_BASE:
|
||||
val = vm_get_const_base(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||
break;
|
||||
default:
|
||||
rb_bug("putspecialobject insn: unknown value_type");
|
||||
}
|
||||
|
@ -944,7 +947,7 @@ defineclass
|
|||
rb_bug("unknown defineclass type: %d", (int)define_type);
|
||||
}
|
||||
|
||||
COPY_CREF(class_iseq->cref_stack, vm_cref_push(th, klass, NOEX_PUBLIC));
|
||||
COPY_CREF(class_iseq->cref_stack, vm_cref_push(th, klass, NOEX_PUBLIC, NULL));
|
||||
|
||||
/* enter scope */
|
||||
vm_push_frame(th, class_iseq,
|
||||
|
|
1
node.h
1
node.h
|
@ -262,6 +262,7 @@ typedef struct RNode {
|
|||
|
||||
/* 0..4:T_TYPES, 5:FL_MARK, 6:reserved, 7:NODE_FL_NEWLINE */
|
||||
#define NODE_FL_NEWLINE (((VALUE)1)<<7)
|
||||
#define NODE_FL_CREF_PUSHED_BY_EVAL NODE_FL_NEWLINE
|
||||
|
||||
#define NODE_TYPESHIFT 8
|
||||
#define NODE_TYPEMASK (((VALUE)0x7f)<<NODE_TYPESHIFT)
|
||||
|
|
|
@ -216,10 +216,29 @@ class TestModule < Test::Unit::TestCase
|
|||
remove_rake_mixins(remove_json_mixins(remove_pp_mixins(String.ancestors))))
|
||||
end
|
||||
|
||||
CLASS_EVAL = 2
|
||||
@@class_eval = 'b'
|
||||
|
||||
def test_class_eval
|
||||
Other.class_eval("CLASS_EVAL = 1")
|
||||
assert_equal(1, Other::CLASS_EVAL)
|
||||
assert(Other.constants.include?(:CLASS_EVAL))
|
||||
assert_equal(2, Other.class_eval { CLASS_EVAL })
|
||||
|
||||
Other.class_eval("@@class_eval = 'a'")
|
||||
assert_equal('a', Other.class_variable_get(:@@class_eval))
|
||||
assert_equal('b', Other.class_eval { @@class_eval })
|
||||
|
||||
Other.class_eval do
|
||||
module_function
|
||||
|
||||
def class_eval_test
|
||||
"foo"
|
||||
end
|
||||
end
|
||||
assert("foo", Other.class_eval_test)
|
||||
|
||||
assert_equal([Other], Other.class_eval { |*args| args })
|
||||
end
|
||||
|
||||
def test_const_defined?
|
||||
|
@ -451,7 +470,7 @@ class TestModule < Test::Unit::TestCase
|
|||
|
||||
def test_class_variable_get
|
||||
c = Class.new
|
||||
c.class_eval { @@foo = :foo }
|
||||
c.class_eval('@@foo = :foo')
|
||||
assert_equal(:foo, c.class_variable_get(:@@foo))
|
||||
assert_raise(NameError) { c.class_variable_get(:@@bar) } # c.f. instance_variable_get
|
||||
assert_raise(NameError) { c.class_variable_get(:foo) }
|
||||
|
@ -460,13 +479,13 @@ class TestModule < Test::Unit::TestCase
|
|||
def test_class_variable_set
|
||||
c = Class.new
|
||||
c.class_variable_set(:@@foo, :foo)
|
||||
assert_equal(:foo, c.class_eval { @@foo })
|
||||
assert_equal(:foo, c.class_eval('@@foo'))
|
||||
assert_raise(NameError) { c.class_variable_set(:foo, 1) }
|
||||
end
|
||||
|
||||
def test_class_variable_defined
|
||||
c = Class.new
|
||||
c.class_eval { @@foo = :foo }
|
||||
c.class_eval('@@foo = :foo')
|
||||
assert_equal(true, c.class_variable_defined?(:@@foo))
|
||||
assert_equal(false, c.class_variable_defined?(:@@bar))
|
||||
assert_raise(NameError) { c.class_variable_defined?(:foo) }
|
||||
|
@ -474,7 +493,7 @@ class TestModule < Test::Unit::TestCase
|
|||
|
||||
def test_remove_class_variable
|
||||
c = Class.new
|
||||
c.class_eval { @@foo = :foo }
|
||||
c.class_eval('@@foo = :foo')
|
||||
c.class_eval { remove_class_variable(:@@foo) }
|
||||
assert_equal(false, c.class_variable_defined?(:@@foo))
|
||||
end
|
||||
|
|
|
@ -416,12 +416,20 @@ class TestObject < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
class InstanceExec
|
||||
INSTANCE_EXEC = 123
|
||||
end
|
||||
|
||||
def test_instance_exec
|
||||
x = 1.instance_exec(42) {|a| self + a }
|
||||
assert_equal(43, x)
|
||||
|
||||
x = "foo".instance_exec("bar") {|a| self + a }
|
||||
assert_equal("foobar", x)
|
||||
|
||||
assert_raise(NameError) do
|
||||
InstanceExec.new.instance_exec { INSTANCE_EXEC }
|
||||
end
|
||||
end
|
||||
|
||||
def test_extend
|
||||
|
|
|
@ -524,8 +524,9 @@ typedef struct {
|
|||
#define VM_CALL_SUPER_BIT (0x01 << 7)
|
||||
#define VM_CALL_OPT_SEND_BIT (0x01 << 8)
|
||||
|
||||
#define VM_SPECIAL_OBJECT_VMCORE 0x01
|
||||
#define VM_SPECIAL_OBJECT_CBASE 0x02
|
||||
#define VM_SPECIAL_OBJECT_VMCORE 0x01
|
||||
#define VM_SPECIAL_OBJECT_CBASE 0x02
|
||||
#define VM_SPECIAL_OBJECT_CONST_BASE 0x03
|
||||
|
||||
#define VM_FRAME_MAGIC_METHOD 0x11
|
||||
#define VM_FRAME_MAGIC_BLOCK 0x21
|
||||
|
|
10
vm_eval.c
10
vm_eval.c
|
@ -17,7 +17,7 @@ static inline VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *a
|
|||
static inline VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv);
|
||||
static inline VALUE vm_backtrace(rb_thread_t *th, int lev);
|
||||
static int vm_backtrace_each(rb_thread_t *th, int lev, rb_backtrace_iter_func *iter, void *arg);
|
||||
static NODE *vm_cref_push(rb_thread_t *th, VALUE klass, int noex);
|
||||
static NODE *vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr);
|
||||
static VALUE vm_exec(rb_thread_t *th);
|
||||
static void vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref);
|
||||
static int vm_collect_local_variables_in_heap(rb_thread_t *th, VALUE *dfp, VALUE ary);
|
||||
|
@ -1161,16 +1161,18 @@ yield_under(VALUE under, VALUE self, VALUE values)
|
|||
{
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
rb_block_t block, *blockptr;
|
||||
NODE *cref = vm_cref_push(th, under, NOEX_PUBLIC);
|
||||
NODE *cref;
|
||||
|
||||
if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) {
|
||||
block = *blockptr;
|
||||
block.self = self;
|
||||
th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
|
||||
}
|
||||
cref = vm_cref_push(th, under, NOEX_PUBLIC, &block);
|
||||
cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
|
||||
|
||||
if (values == Qundef) {
|
||||
return vm_yield_with_cref(th, 0, 0, cref);
|
||||
return vm_yield_with_cref(th, 1, &self, cref);
|
||||
}
|
||||
else {
|
||||
return vm_yield_with_cref(th, RARRAY_LENINT(values), RARRAY_PTR(values), cref);
|
||||
|
@ -1181,7 +1183,7 @@ yield_under(VALUE under, VALUE self, VALUE values)
|
|||
static VALUE
|
||||
eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
|
||||
{
|
||||
NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC);
|
||||
NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC, NULL);
|
||||
|
||||
if (rb_safe_level() >= 4) {
|
||||
StringValue(src);
|
||||
|
|
|
@ -1066,14 +1066,17 @@ vm_get_cref(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
|
|||
}
|
||||
|
||||
static NODE *
|
||||
vm_cref_push(rb_thread_t *th, VALUE klass, int noex)
|
||||
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);
|
||||
cref->nd_file = 0;
|
||||
cref->nd_visi = noex;
|
||||
|
||||
if (cfp) {
|
||||
if (blockptr) {
|
||||
cref->nd_next = vm_get_cref(blockptr->iseq, blockptr->lfp, blockptr->dfp);
|
||||
}
|
||||
else if (cfp) {
|
||||
cref->nd_next = vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
|
||||
}
|
||||
|
||||
|
@ -1096,6 +1099,23 @@ vm_get_cbase(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
|
|||
return klass;
|
||||
}
|
||||
|
||||
static inline VALUE
|
||||
vm_get_const_base(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
|
||||
{
|
||||
NODE *cref = vm_get_cref(iseq, lfp, dfp);
|
||||
VALUE klass = Qundef;
|
||||
|
||||
while (cref) {
|
||||
if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL) &&
|
||||
(klass = cref->nd_clss) != 0) {
|
||||
break;
|
||||
}
|
||||
cref = cref->nd_next;
|
||||
}
|
||||
|
||||
return klass;
|
||||
}
|
||||
|
||||
static inline void
|
||||
vm_check_if_namespace(VALUE klass)
|
||||
{
|
||||
|
@ -1117,12 +1137,16 @@ 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->lfp, th->cfp->dfp);
|
||||
const NODE *cref = root_cref;
|
||||
const NODE *cref = vm_get_cref(iseq, th->cfp->lfp, th->cfp->dfp);
|
||||
const NODE *root_cref = NULL;
|
||||
VALUE klass = orig_klass;
|
||||
|
||||
while (cref && cref->nd_next) {
|
||||
klass = cref->nd_clss;
|
||||
if (!(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL)) {
|
||||
klass = cref->nd_clss;
|
||||
if (root_cref == NULL)
|
||||
root_cref = cref;
|
||||
}
|
||||
cref = cref->nd_next;
|
||||
|
||||
if (!NIL_P(klass)) {
|
||||
|
@ -1149,8 +1173,10 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
|
|||
}
|
||||
|
||||
/* search self */
|
||||
klass = root_cref->nd_clss;
|
||||
if (NIL_P(klass)) {
|
||||
if (root_cref && !NIL_P(root_cref->nd_clss)) {
|
||||
klass = root_cref->nd_clss;
|
||||
}
|
||||
else {
|
||||
klass = CLASS_OF(th->cfp->self);
|
||||
}
|
||||
|
||||
|
@ -1178,7 +1204,8 @@ vm_get_cvar_base(NODE *cref)
|
|||
VALUE klass;
|
||||
|
||||
while (cref && cref->nd_next &&
|
||||
(NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON))) {
|
||||
(NIL_P(cref->nd_clss) || FL_TEST(cref->nd_clss, FL_SINGLETON) ||
|
||||
(cref->flags & NODE_FL_CREF_PUSHED_BY_EVAL))) {
|
||||
cref = cref->nd_next;
|
||||
|
||||
if (!cref->nd_next) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче