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

ruby-changes:13310

From: matz <ko1@a...>
Date: Thu, 24 Sep 2009 13:44:11 +0900 (JST)
Subject: [ruby-changes:13310] Ruby:r25073 (trunk): * proc.c (mnew): generate method object that wraps method_missing,

matz	2009-09-24 13:42:28 +0900 (Thu, 24 Sep 2009)

  New Revision: 25073

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

  Log:
    * proc.c (mnew): generate method object that wraps method_missing,
      when #respond_to_missing? is defined.
    
    * test/ruby/test_object.rb (test_respond_to_missing): add test
      suites for #respond_to_missing? changes.

  Modified files:
    trunk/ChangeLog
    trunk/proc.c
    trunk/test/ruby/test_object.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 25072)
+++ ChangeLog	(revision 25073)
@@ -1,3 +1,11 @@
+Thu Sep 24 13:32:53 2009  Yukihiro Matsumoto  <matz@r...>
+
+	* proc.c (mnew): generate method object that wraps method_missing,
+	  when #respond_to_missing? is defined.
+
+	* test/ruby/test_object.rb (test_respond_to_missing): add test
+	  suites for #respond_to_missing? changes.
+
 Thu Sep 24 09:41:42 2009  Marc-Andre Lafortune  <ruby-core@m...>
 
 	* lib/mathn.rb (Bignum#**): Fixed bignum**fixnum that was broken when
Index: proc.c
===================================================================
--- proc.c	(revision 25072)
+++ proc.c	(revision 25073)
@@ -884,6 +884,19 @@
 }
 
 static VALUE
+missing_wrap(VALUE dummy, VALUE args, int argc, VALUE *argv)
+{
+    VALUE new_args = rb_ary_new4(argc, argv);
+    VALUE obj = RARRAY_PTR(args)[0];
+    VALUE sym = RARRAY_PTR(args)[1];
+    
+
+    rb_ary_unshift(new_args, sym);
+    return rb_funcall2(obj, rb_intern("method_missing"), 
+		       check_argc(RARRAY_LEN(new_args)), RARRAY_PTR(new_args));
+}
+
+static VALUE
 mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope)
 {
     VALUE method;
@@ -896,6 +909,14 @@
   again:
     me = rb_method_entry(klass, id);
     if (UNDEFINED_METHOD_ENTRY_P(me)) {
+	ID rmiss = rb_intern("respond_to_missing?");
+	VALUE sym = ID2SYM(id);
+
+	if (!rb_method_basic_definition_p(klass, rmiss)) {
+	    if (RTEST(rb_funcall(obj, rmiss, 1, sym))) {
+		return rb_proc_new(missing_wrap, rb_assoc_new(obj, sym));
+	    }
+	}
 	rb_print_undef(klass, id, 0);
     }
     def = me->def;
Index: test/ruby/test_object.rb
===================================================================
--- test/ruby/test_object.rb	(revision 25072)
+++ test/ruby/test_object.rb	(revision 25073)
@@ -304,6 +304,39 @@
     end
   end
 
+  def test_respond_to_missing
+    c = Class.new
+    c.class_eval do
+      def respond_to_missing?(id)
+        if id == :foobar
+          true
+        else
+          false
+        end
+      end
+      def method_missing(id,*args)
+        if id == :foobar
+          return [:foo, *args]
+        else
+          super
+        end
+      end
+    end
+
+    foo = c.new
+    assert_equal([:foo], foo.foobar);
+    assert_equal([:foo, 1], foo.foobar(1));
+    assert(foo.respond_to?(:foobar))
+    assert_equal(false, foo.respond_to?(:foobarbaz))
+    assert_raise(NoMethodError) do
+      foo.foobarbaz
+    end
+
+    foobar = foo.method(:foobar)
+    assert_equal([:foo], foobar.call);
+    assert_equal([:foo, 1], foobar.call(1));
+  end
+
   def test_send_with_no_arguments
     assert_raise(ArgumentError) { 1.send }
   end

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

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