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

ruby-changes:25362

From: shugo <ko1@a...>
Date: Fri, 2 Nov 2012 14:48:42 +0900 (JST)
Subject: [ruby-changes:25362] shugo:r37418 (trunk): * string.c (sym_to_proc, sym_call): A Proc created by Symbol#to_proc

shugo	2012-11-02 14:48:29 +0900 (Fri, 02 Nov 2012)

  New Revision: 37418

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

  Log:
    * string.c (sym_to_proc, sym_call): A Proc created by Symbol#to_proc
      should close over the current refinements.
      [ruby-dev:46345] [Bug #7261]
    
    * vm_eval.c (rb_call0, rb_search_method_entry,
      rb_funcall_passing_block_with_refinements): add a new argument
      `refinements' for the above changes.
    
    * test/ruby/test_refinement.rb: related test.

  Modified files:
    trunk/ChangeLog
    trunk/include/ruby/ruby.h
    trunk/string.c
    trunk/test/ruby/test_refinement.rb
    trunk/vm_eval.c

Index: include/ruby/ruby.h
===================================================================
--- include/ruby/ruby.h	(revision 37417)
+++ include/ruby/ruby.h	(revision 37418)
@@ -1317,6 +1317,8 @@
 VALUE rb_funcall2(VALUE, ID, int, const VALUE*);
 VALUE rb_funcall3(VALUE, ID, int, const VALUE*);
 VALUE rb_funcall_passing_block(VALUE, ID, int, const VALUE*);
+VALUE rb_funcall_passing_block_with_refinements(VALUE, ID, int,
+						const VALUE*, VALUE);
 int rb_scan_args(int, const VALUE*, const char*, ...);
 VALUE rb_call_super(int, const VALUE*);
 
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 37417)
+++ ChangeLog	(revision 37418)
@@ -1,3 +1,15 @@
+Fri Nov  2 14:47:53 2012  Shugo Maeda  <shugo@r...>
+
+	* string.c (sym_to_proc, sym_call): A Proc created by Symbol#to_proc
+	  should close over the current refinements.
+	  [ruby-dev:46345] [Bug #7261]
+
+	* vm_eval.c (rb_call0, rb_search_method_entry,
+	  rb_funcall_passing_block_with_refinements): add a new argument
+	  `refinements' for the above changes.
+
+	* test/ruby/test_refinement.rb: related test.
+
 Fri Nov  2 08:24:28 2012  Nobuyoshi Nakada  <nobu@r...>
 
 	* proc.c (top_define_method): new method, main.define_method.
Index: string.c
===================================================================
--- string.c	(revision 37417)
+++ string.c	(revision 37418)
@@ -14,6 +14,8 @@
 #include "ruby/ruby.h"
 #include "ruby/re.h"
 #include "ruby/encoding.h"
+#include "node.h"
+#include "eval_intern.h"
 #include "internal.h"
 #include <assert.h>
 
@@ -7605,15 +7607,18 @@
 }
 
 static VALUE
-sym_call(VALUE args, VALUE sym, int argc, VALUE *argv)
+sym_call(VALUE args, VALUE p, int argc, VALUE *argv)
 {
     VALUE obj;
+    NODE *memo = RNODE(p);
 
     if (argc < 1) {
 	rb_raise(rb_eArgError, "no receiver given");
     }
     obj = argv[0];
-    return rb_funcall_passing_block(obj, (ID)sym, argc - 1, argv + 1);
+    return rb_funcall_passing_block_with_refinements(obj, (ID) memo->u1.id,
+						     argc - 1, argv + 1,
+						     memo->u2.value);
 }
 
 /*
@@ -7633,25 +7638,32 @@
     VALUE proc;
     long id, index;
     VALUE *aryp;
+    const NODE *cref = rb_vm_cref();
 
-    if (!sym_proc_cache) {
-	sym_proc_cache = rb_ary_tmp_new(SYM_PROC_CACHE_SIZE * 2);
-	rb_gc_register_mark_object(sym_proc_cache);
-	rb_ary_store(sym_proc_cache, SYM_PROC_CACHE_SIZE*2 - 1, Qnil);
-    }
-
     id = SYM2ID(sym);
-    index = (id % SYM_PROC_CACHE_SIZE) << 1;
+    if (NIL_P(cref->nd_refinements)) {
+	if (!sym_proc_cache) {
+	    sym_proc_cache = rb_ary_tmp_new(SYM_PROC_CACHE_SIZE * 2);
+	    rb_gc_register_mark_object(sym_proc_cache);
+	    rb_ary_store(sym_proc_cache, SYM_PROC_CACHE_SIZE*2 - 1, Qnil);
+	}
 
-    aryp = RARRAY_PTR(sym_proc_cache);
-    if (aryp[index] == sym) {
-	return aryp[index + 1];
+	index = (id % SYM_PROC_CACHE_SIZE) << 1;
+	aryp = RARRAY_PTR(sym_proc_cache);
+	if (aryp[index] == sym) {
+	    return aryp[index + 1];
+	}
+	else {
+	    proc = rb_proc_new(sym_call,
+			       (VALUE) NEW_MEMO(id, Qnil, 0));
+	    aryp[index] = sym;
+	    aryp[index + 1] = proc;
+	    return proc;
+	}
     }
     else {
-	proc = rb_proc_new(sym_call, (VALUE)id);
-	aryp[index] = sym;
-	aryp[index + 1] = proc;
-	return proc;
+	return rb_proc_new(sym_call,
+			   (VALUE) NEW_MEMO(id, cref->nd_refinements, 0));
     }
 }
 
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 37417)
+++ vm_eval.c	(revision 37418)
@@ -266,7 +266,8 @@
 }
 
 static inline rb_method_entry_t *
-    rb_search_method_entry(VALUE recv, ID mid, VALUE *defined_class_ptr);
+    rb_search_method_entry(VALUE refinements, VALUE recv, ID mid,
+			   VALUE *defined_class_ptr);
 static inline int rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type scope, VALUE self);
 #define NOEX_OK NOEX_NOSUPER
 
@@ -286,10 +287,11 @@
  */
 static inline VALUE
 rb_call0(VALUE recv, ID mid, int argc, const VALUE *argv,
-	 call_type scope, VALUE self)
+	 call_type scope, VALUE self, VALUE refinements)
 {
     VALUE defined_class;
-    rb_method_entry_t *me = rb_search_method_entry(recv, mid, &defined_class);
+    rb_method_entry_t *me =
+	rb_search_method_entry(refinements, recv, mid, &defined_class);
     rb_thread_t *th = GET_THREAD();
     int call_status = rb_method_call_status(th, me, scope, self);
 
@@ -353,7 +355,7 @@
 	}
     }
 
-    me = rb_search_method_entry(recv, mid, &defined_class);
+    me = rb_search_method_entry(Qnil, recv, mid, &defined_class);
     call_status = rb_method_call_status(th, me, CALL_FCALL, Qundef);
     if (call_status != NOEX_OK) {
 	if (rb_method_basic_definition_p(klass, idMethodMissing)) {
@@ -418,7 +420,8 @@
 }
 
 static inline rb_method_entry_t *
-rb_search_method_entry(VALUE recv, ID mid, VALUE *defined_class_ptr)
+rb_search_method_entry(VALUE refinements, VALUE recv, ID mid,
+		       VALUE *defined_class_ptr)
 {
     VALUE klass = CLASS_OF(recv);
 
@@ -457,7 +460,8 @@
                          rb_id2name(mid), type, (void *)recv, flags, klass);
         }
     }
-    return rb_method_entry_get_with_refinements(Qnil, klass, mid, defined_class_ptr);
+    return rb_method_entry_get_with_refinements(refinements, klass, mid,
+						defined_class_ptr);
 }
 
 static inline int
@@ -521,7 +525,7 @@
 static inline VALUE
 rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope)
 {
-    return rb_call0(recv, mid, argc, argv, scope, Qundef);
+    return rb_call0(recv, mid, argc, argv, scope, Qundef, Qnil);
 }
 
 NORETURN(static void raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv,
@@ -769,6 +773,17 @@
     return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
 }
 
+VALUE
+rb_funcall_passing_block_with_refinements(VALUE recv, ID mid, int argc,
+					  const VALUE *argv,
+					  VALUE refinements)
+{
+    PASS_PASSED_BLOCK_TH(GET_THREAD());
+
+    return rb_call0(recv, mid, argc, argv, CALL_PUBLIC, Qundef,
+		    refinements);
+}
+
 static VALUE
 send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope)
 {
@@ -793,7 +808,7 @@
 	id = rb_to_id(vid);
     }
     PASS_PASSED_BLOCK_TH(th);
-    return rb_call0(recv, id, argc, argv, scope, self);
+    return rb_call0(recv, id, argc, argv, scope, self, Qnil);
 }
 
 /*
Index: test/ruby/test_refinement.rb
===================================================================
--- test/ruby/test_refinement.rb	(revision 37417)
+++ test/ruby/test_refinement.rb	(revision 37418)
@@ -600,4 +600,26 @@
     assert_equal(:m1, m.module_eval { c.new.m1 })
     assert_equal(:m2, m.module_eval { c.new.m2 })
   end
+
+  module SymbolToProc
+    class C
+    end
+
+    module M
+      refine C do
+        def foo
+          "foo"
+        end
+      end
+
+      def self.call_foo
+        c = C.new
+        :foo.to_proc.call(c)
+      end
+    end
+  end
+
+  def test_symbol_to_proc
+    assert_equal("foo", SymbolToProc::M.call_foo)
+  end
 end

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

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