[前][次][番号順一覧][スレッド一覧]

ruby-changes:26205

From: shugo <ko1@a...>
Date: Sat, 8 Dec 2012 00:49:33 +0900 (JST)
Subject: [ruby-changes:26205] shugo:r38262 (trunk): * vm_eval.c (yield_under, eval_under): do not activate refinements

shugo	2012-12-08 00:49:21 +0900 (Sat, 08 Dec 2012)

  New Revision: 38262

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=38262

  Log:
    * vm_eval.c (yield_under, eval_under): do not activate refinements
      of the receiver in module_eval and instance_eval.
    
    * eval.c (ruby_Init_refinement): undef Class#refine.
    
    * eval.c (ruby_Init_refinement): remove Module#using.
    
    * eval.c (ruby_Init_refinement): main.using should be private.
    
    * eval.c (rb_mod_refine): the argument of Module#refine should not
      be a module.
    
    * insns.def (defineclass): do not activate refinements in a class or
      module.

  Modified files:
    trunk/ChangeLog
    trunk/eval.c
    trunk/insns.def
    trunk/test/ruby/test_refinement.rb
    trunk/vm_eval.c
    trunk/vm_insnhelper.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 38261)
+++ ChangeLog	(revision 38262)
@@ -1,3 +1,20 @@
+Sat Dec  8 00:10:34 2012  Shugo Maeda  <shugo@r...>
+
+	* vm_eval.c (yield_under, eval_under): do not activate refinements
+	  of the receiver in module_eval and instance_eval.
+
+	* eval.c (ruby_Init_refinement): undef Class#refine.
+
+	* eval.c (ruby_Init_refinement): remove Module#using.
+
+	* eval.c (ruby_Init_refinement): main.using should be private.
+
+	* eval.c (rb_mod_refine): the argument of Module#refine should not
+	  be a module.
+
+	* insns.def (defineclass): do not activate refinements in a class or
+	  module.
+
 Fri Dec  7 23:42:11 2012  Shugo Maeda  <shugo@r...>
 
 	* ext/refinement/refinement.c: include ruby/ruby.h instead of the
Index: insns.def
===================================================================
--- insns.def	(revision 38261)
+++ insns.def	(revision 38262)
@@ -967,7 +967,6 @@
 		  klass, 0, VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()),
 		  class_iseq->iseq_encoded, GET_SP(),
 		  class_iseq->local_size, 0);
-    rb_vm_using_modules(class_iseq->cref_stack, klass);
     RESTORE_REGS();
 
     INC_VM_STATE_VERSION();
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 38261)
+++ vm_eval.c	(revision 38262)
@@ -1453,7 +1453,6 @@
     }
     cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
     cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
-    rb_vm_using_modules(cref, under);
 
     if (values == Qundef) {
 	return vm_yield_with_cref(th, 1, &self, cref);
@@ -1478,7 +1477,6 @@
     else {
 	SafeStringValue(src);
     }
-    rb_vm_using_modules(cref, under);
 
     return eval_string_with_cref(self, src, Qnil, cref, file, line);
 }
Index: eval.c
===================================================================
--- eval.c	(revision 38261)
+++ eval.c	(revision 38262)
@@ -1039,16 +1039,6 @@
     return module;
 }
 
-static
-void check_class_or_module(VALUE obj)
-{
-    if (!RB_TYPE_P(obj, T_CLASS) && !RB_TYPE_P(obj, T_MODULE)) {
-	VALUE str = rb_inspect(obj);
-	rb_raise(rb_eTypeError, "%s is not a class/module",
-		 StringValuePtr(str));
-    }
-}
-
 static VALUE
 hidden_identity_hash_new()
 {
@@ -1064,7 +1054,7 @@
 {
     VALUE iclass, c, superclass = klass;
 
-    check_class_or_module(klass);
+    Check_Type(klass, T_CLASS);
     Check_Type(module, T_MODULE);
     if (NIL_P(cref->nd_refinements)) {
 	cref->nd_refinements = hidden_identity_hash_new();
@@ -1098,18 +1088,7 @@
     rb_hash_aset(cref->nd_refinements, klass, iclass);
 }
 
-void rb_using_module(NODE *cref, VALUE module);
-
 static int
-using_module_i(VALUE module, VALUE val, VALUE arg)
-{
-    NODE *cref = (NODE *) arg;
-
-    rb_using_module(cref, module);
-    return ST_CONTINUE;
-}
-
-static int
 using_refinement(VALUE klass, VALUE module, VALUE arg)
 {
     NODE *cref = (NODE *) arg;
@@ -1123,70 +1102,14 @@
 {
     ID id_refinements;
     VALUE refinements;
-    ID id_using_modules;
-    VALUE using_modules;
 
-    check_class_or_module(module);
-    CONST_ID(id_using_modules, "__using_modules__");
-    using_modules = rb_attr_get(module, id_using_modules);
-    if (!NIL_P(using_modules)) {
-	rb_hash_foreach(using_modules, using_module_i, (VALUE) cref);
-    }
+    Check_Type(module, T_MODULE);
     CONST_ID(id_refinements, "__refinements__");
     refinements = rb_attr_get(module, id_refinements);
     if (NIL_P(refinements)) return;
     rb_hash_foreach(refinements, using_refinement, (VALUE) cref);
 }
 
-
-static int
-check_cyclic_using(VALUE mod, VALUE _, VALUE search)
-{
-    VALUE using_modules;
-    ID id_using_modules;
-    CONST_ID(id_using_modules, "__using_modules__");
-
-    if (mod == search) {
-	rb_raise(rb_eArgError, "cyclic using detected");
-    }
-
-    using_modules = rb_attr_get(mod, id_using_modules);
-    if (!NIL_P(using_modules)) {
-	rb_hash_foreach(using_modules, check_cyclic_using, search);
-    }
-
-    return ST_CONTINUE;
-}
-
-/*
- *  call-seq:
- *     using(module)    -> self
- *
- *  Import class refinements from <i>module</i> into the receiver.
- */
-
-static VALUE
-rb_mod_using(VALUE self, VALUE module)
-{
-    NODE *cref = rb_vm_cref();
-    ID id_using_modules;
-    VALUE using_modules;
-
-    Check_Type(module, T_MODULE);
-    check_cyclic_using(module, 0, self);
-    CONST_ID(id_using_modules, "__using_modules__");
-    using_modules = rb_attr_get(self, id_using_modules);
-    if (NIL_P(using_modules)) {
-	using_modules = hidden_identity_hash_new();
-	rb_ivar_set(self, id_using_modules, using_modules);
-    }
-    rb_hash_aset(using_modules, module, Qtrue);
-    rb_using_module(cref, module);
-    rb_clear_cache();
-    rb_funcall(module, rb_intern("used"), 1, self);
-    return self;
-}
-
 VALUE rb_refinement_module_get_refined_class(VALUE module)
 {
     ID id_refined_class;
@@ -1245,7 +1168,7 @@
     if (!rb_block_given_p()) {
         rb_raise(rb_eArgError, "no block given");
     }
-    check_class_or_module(klass);
+    Check_Type(klass, T_CLASS);
     CONST_ID(id_refinements, "__refinements__");
     refinements = rb_attr_get(module, id_refinements);
     if (NIL_P(refinements)) {
@@ -1645,10 +1568,11 @@
 void
 ruby_Init_refinement(void)
 {
-    rb_define_private_method(rb_cModule, "using", rb_mod_using, 1);
     rb_define_private_method(rb_cModule, "refine", rb_mod_refine, 1);
+    rb_undef_method(rb_cClass, "refine");
     rb_define_method(rb_cModule, "refinements", rb_mod_refinements, 0);
-    rb_define_singleton_method(rb_vm_top_self(), "using", top_using, 1);
+    rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
+			     "using", top_using, 1);
 }
 
 #if defined __GNUC__ && __GNUC__ >= 4
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 38261)
+++ vm_insnhelper.c	(revision 38262)
@@ -920,41 +920,6 @@
     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;
-
-    if (NIL_P(klass)) return;
-    CONST_ID(id_using_modules, "__using_modules__");
-    using_modules = rb_attr_get(klass, id_using_modules);
-    if (NIL_P(using_modules) && BUILTIN_TYPE(klass) == T_CLASS) {
-	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);
-	}
-    }
-    if (!NIL_P(using_modules)) {
-	rb_hash_foreach(using_modules, vm_using_module_i,
-			(VALUE) cref);
-    }
-    rb_using_module(cref, klass);
-}
-
 static VALUE
 check_match(VALUE pattern, VALUE target, enum vm_check_match_type type)
 {
@@ -1694,42 +1659,13 @@
     return vm_call_method(th, reg_cfp, &ci_entry);
 }
 
-static VALUE
-copy_refinement_iclass(VALUE iclass, VALUE superclass)
-{
-    VALUE result, c;
-
-    Check_Type(iclass, T_ICLASS);
-    c = result = rb_include_class_new(RBASIC(iclass)->klass, superclass);
-    RCLASS_REFINED_CLASS(c) = RCLASS_REFINED_CLASS(iclass);
-    iclass = RCLASS_SUPER(iclass);
-    while (iclass && BUILTIN_TYPE(iclass) == T_ICLASS) {
-	c = RCLASS_SUPER(c) = rb_include_class_new(RBASIC(iclass)->klass,
-						   RCLASS_SUPER(c));
-	RCLASS_REFINED_CLASS(c) = RCLASS_REFINED_CLASS(iclass);
-	iclass = RCLASS_SUPER(iclass);
-    }
-    return result;
-}
-
-static VALUE
+static inline VALUE
 find_refinement(VALUE refinements, VALUE klass)
 {
-    VALUE refinement;
-
     if (NIL_P(refinements)) {
 	return Qnil;
     }
-    refinement = rb_hash_lookup(refinements, klass);
-    if (NIL_P(refinement) &&
-	BUILTIN_TYPE(klass) == T_ICLASS) {
-	refinement = rb_hash_lookup(refinements,
-				    RBASIC(klass)->klass);
-	if (!NIL_P(refinement)) {
-	    refinement = copy_refinement_iclass(refinement, klass);
-	}
-    }
-    return refinement;
+    return rb_hash_lookup(refinements, klass);
 }
 
 static int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2);
Index: test/ruby/test_refinement.rb
===================================================================
--- test/ruby/test_refinement.rb	(revision 38261)
+++ test/ruby/test_refinement.rb	(revision 38262)
@@ -175,7 +175,8 @@
   def test_module_eval
     foo = Foo.new
     assert_equal("Foo#x", foo.x)
-    assert_equal("FooExt#x", FooExt.module_eval { foo.x })
+    assert_equal("Foo#x", FooExt.module_eval { foo.x })
+    assert_equal("Foo#x", FooExt.module_eval("foo.x"))
     assert_equal("Foo#x", foo.x)
   end
 
@@ -242,14 +243,15 @@
     assert_not_equal(RefineSameClass::REFINEMENT1, RefineSameClass::REFINEMENT3)
   end
 
+  module FixnumFooExt
+    refine Fixnum do
+      def foo; "foo"; end
+    end
+  end
+
   def test_respond_to?
-    m = Module.new {
-      refine Fixnum do
-        def foo; "foo"; end
-      end
-    }
     assert_equal(false, 1.respond_to?(:foo))
-    assert_equal(true, m.module_eval { 1.respond_to?(:foo) })
+    assert_equal(true, eval_using(FixnumFooExt, "1.respond_to?(:foo)"))
     assert_equal(false, 1.respond_to?(:foo))
   end
 
@@ -274,185 +276,49 @@
     assert_equal(1, eval_using(ArrayEachExt, "[1, 2, 3].min"))
   end
 
-  def test_module_inclusion
-    m1 = Module.new {
+  module RefinePrependedClass
+    module M1
       def foo
-        "m1#foo"
+        super << :m1
       end
+    end
 
-      def bar
-        "m1#bar"
-      end
-    }
-    m2 = Module.new {
-      def bar
-        "m2#bar"
-      end
+    class C
+      prepend M1
 
-      def baz
-        "m2#baz"
-      end
-    }
-    m3 = Module.new {
-      def baz
-        "m3#baz"
-      end
-    }
-    include_proc = Proc.new {
-      include m3, m2
-    }
-    m = Module.new {
-      refine String do
-        include m1
-        module_eval(&include_proc)
-
-        def call_foo
-          foo
-        end
-
-        def call_bar
-          bar
-        end
-
-        def call_baz
-          baz
-        end
-      end
-
-      def self.call_foo(s)
-        s.foo
-      end
-
-      def self.call_bar(s)
-        s.bar
-      end
-
-      def self.call_baz(s)
-        s.baz
-      end
-    }
-    assert_equal("m1#foo", m.module_eval { "abc".foo })
-    assert_equal("m2#bar", m.module_eval { "abc".bar })
-    assert_equal("m3#baz", m.module_eval { "abc".baz })
-    assert_equal("m1#foo", m.module_eval { "abc".call_foo })
-    assert_equal("m2#bar", m.module_eval { "abc".call_bar })
-    assert_equal("m3#baz", m.module_eval { "abc".call_baz })
-    assert_equal("m1#foo", m.call_foo("abc"))
-    assert_equal("m2#bar", m.call_bar("abc"))
-    assert_equal("m3#baz", m.call_baz("abc"))
-  end
-
-  def test_refine_prepended_class
-    m1 = Module.new {
       def foo
-        super << :m1
-      end
-    }
-    c = Class.new {
-      prepend m1
-
-      def foo
         [:c]
       end
-    }
-    m2 = Module.new {
-      refine c do
+    end
+
+    module M2
+      refine C do
         def foo
           super << :m2
         end
       end
-    }
-    obj = c.new
-    assert_equal([:c, :m1, :m2], m2.module_eval { obj.foo })
+    end
   end
 
-  def test_refine_module_without_overriding
+  def test_refine_prepended_class
+    x = eval_using(RefinePrependedClass::M2,
+                   "TestRefinement::RefinePrependedClass::C.new.foo")
+    assert_equal([:c, :m1, :m2], x)
+  end
+
+  def test_refine_module
     m1 = Module.new
-    c = Class.new {
-      include m1
-    }
-    m2 = Module.new {
-      refine m1 do
+    assert_raise(TypeError) do
+      Module.new {
+        refine m1 do
         def foo
           :m2
         end
-      end
-    }
-    obj = c.new
-    assert_equal(:m2, m2.module_eval { obj.foo })
-  end
-
-  def test_refine_module_with_overriding
-    m1 = Module.new {
-      def foo
-        super << :m1
-      end
-    }
-    c0 = Class.new {
-      def foo
-        [:c0]
-      end
-    }
-    c = Class.new(c0) {
-      include m1
-    }
-    m2 = Module.new {
-      refine m1 do
-        def foo
-          super << :m2
         end
-      end
-    }
-    obj = c.new
-    assert_equal([:c0, :m1, :m2], m2.module_eval { obj.foo })
+      }
+    end
   end
 
-  def test_refine_module_with_double_overriding
-    m1 = Module.new {
-      def foo
-        [:m1]
-      end
-    }
-    c = Class.new {
-      include m1
-    }
-    m2 = Module.new {
-      refine m1 do
-        def foo
-          super << :m2
-        end
-      end
-    }
-    m3 = Module.new {
-      using m2
-      refine m1 do
-        def foo
-          super << :m3
-        end
-      end
-    }
-    obj = c.new
-    assert_equal([:m1, :m2, :m3], m3.module_eval { obj.foo })
-  end
-
-  def test_refine_module_and_call_superclass_method
-    m1 = Module.new
-    c1 = Class.new {
-      def foo
-        "c1#foo"
-      end
-    }
-    c2 = Class.new(c1) {
-      include m1
-    }
-    m2 = Module.new {
-      refine m1 do
-      end
-    }
-    obj = c2.new
-    assert_equal("c1#foo", m2.module_eval { obj.foo })
-  end
-
   def test_refine_neither_class_nor_module
     assert_raise(TypeError) do
       Module.new {
@@ -474,15 +340,16 @@
     end
   end
 
-  def test_refine_in_class_and_class_eval
-    c = Class.new {
-      refine Fixnum do
-        def foo
-          "c"
+  def test_refine_in_class
+    assert_raise(NoMethodError) do
+      Class.new {
+        refine Fixnum do
+          def foo
+            "c"
+          end
         end
-      end
-    }
-    assert_equal("c", c.class_eval { 123.foo })
+      }
+    end
   end
 
   def test_main_using
@@ -510,19 +377,33 @@
     INPUT
   end
 
+  def test_main_using_is_private
+    assert_raise(NoMethodError) do
+      eval("self.using Module.new", TOPLEVEL_BINDING)
+    end
+  end
+
   def test_no_kernel_using
     assert_raise(NoMethodError) do
       using Module.new
     end
   end
 
+  def test_no_module_using
+    assert_raise(NoMethodError) do
+      Module.new {
+        using Module.new
+      }
+    end
+  end
+
+  class UsingClass
+  end
+
   def test_module_using_class
     c = Class.new
-    m = Module.new
     assert_raise(TypeError) do
-      m.module_eval do
-        using c
-      end
+      eval("using TestRefinement::UsingClass", TOPLEVEL_BINDING)
     end
   end
 
@@ -572,25 +453,6 @@
     assert_equal({c => c_ext}, m.refinements)
   end
 
-  def test_refinements_no_recursion
-    c1 = Class.new
-    c1_ext = nil
-    m1 = Module.new {
-      refine c1 do
-        c1_ext = self
-      end
-    }
-    c2 = Class.new
-    c2_ext = nil
-    m2 = Module.new {
-      using m1
-      refine c2 do
-        c2_ext = self
-      end
-    }
-    assert_equal({c2 => c2_ext}, m2.refinements)
-  end
-
   def test_refine_without_block
     c1 = Class.new
     e = assert_raise(ArgumentError) {
@@ -601,76 +463,6 @@
     assert_equal("no block given", e.message)
   end
 
-  module IndirectUsing
-    class C
-    end
-
-    module M1
-      refine C do
-        def m1
-          :m1
-        end
-      end
-    end
-
-    module M2
-      refine C do
-        def m2
-          :m2
-        end
-      end
-    end
-
-    module M3
-      using M1
-      using M2
-    end
-
-    module M
-      using M3
-
-      def self.call_m1
-        C.new.m1
-      end
-
-      def self.call_m2
-        C.new.m2
-      end
-    end
-  end
-
-  def test_indirect_using
-    assert_equal(:m1, IndirectUsing::M.call_m1)
-    assert_equal(:m2, IndirectUsing::M.call_m2)
-  end
-
-  def test_indirect_using_module_eval
-    c = Class.new
-    m1 = Module.new {
-      refine c do
-        def m1
-          :m1
-        end
-      end
-    }
-    m2 = Module.new {
-      refine c do
-        def m2
-          :m2
-        end
-      end
-    }
-    m3 = Module.new {
-      using m1
-      using m2
-    }
-    m = Module.new {
-      using m3
-    }
-    assert_equal(:m1, m.module_eval { c.new.m1 })
-    assert_equal(:m2, m.module_eval { c.new.m2 })
-  end
-
   module SymbolToProc
     class C
     end
@@ -722,67 +514,7 @@
                  m.refinements[c].inspect)
   end
 
-  module InlineMethodCache
-    class C
-      def foo
-        "original"
-      end
-    end
-
-    module M
-      refine C do
-        def foo
-          "refined"
-        end
-      end
-    end
-  end
-
-  def test_inline_method_cache
-    c = InlineMethodCache::C.new
-    f = Proc.new { c.foo }
-    assert_equal("original", f.call)
-    assert_equal("refined", InlineMethodCache::M.module_eval(&f))
-    assert_equal("original", f.call)
-  end
-
-  module UsingMethodCache
-    class C
-      def foo
-        "original"
-      end
-    end
-
-    module M1
-      refine C do
-        def foo
-          "M1"
-        end
-      end
-    end
-
-    module M2
-      refine C do
-        def foo
-          "M2"
-        end
-      end
-    end
-
-    module M
-      c = C.new
-      ORIGINAL_FOO = c.foo
-      using M1
-      c.foo
-      using M2
-      M2_FOO = c.foo
-    end
-  end
-
   def test_using_method_cache
-    assert_equal("original", UsingMethodCache::M::ORIGINAL_FOO)
-    assert_equal("M2", UsingMethodCache::M::M2_FOO)
-
     assert_in_out_err([], <<-INPUT, %w(:M1 :M2), /Refinements are experimental/)
       require "refinement"
 
@@ -816,28 +548,7 @@
     INPUT
   end
 
-  def test_circular_using_is_not_allowed
-    a = Module.new
-    b = Module.new
-
-    assert_raise ArgumentError do
-      a.module_eval do
-        using a
-      end
-    end
-
-    b.module_eval do
-      using a
-    end
-
-    assert_raise ArgumentError do
-      a.module_eval do
-        using b
-      end
-    end
-  end
-
-  module RedifineRefinedMethod
+  module RedefineRefinedMethod
     class C
       def foo
         "original"
@@ -860,10 +571,19 @@
   end
 
   def test_redefine_refined_method
-    c = RedifineRefinedMethod::C.new
-    assert_equal("refined", RedifineRefinedMethod::M.module_eval { c.foo })
+    x = eval_using(RedefineRefinedMethod::M,
+                   "TestRefinement::RedefineRefinedMethod::C.new.foo")
+    assert_equal("refined", x)
   end
 
+  module StringExt
+    refine String do
+      def foo
+        "foo"
+      end
+    end
+  end
+
   private
 
   def eval_using(mod, s)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]