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

ruby-changes:13362

From: matz <ko1@a...>
Date: Mon, 28 Sep 2009 12:09:51 +0900 (JST)
Subject: [ruby-changes:13362] Ruby:r25129 (trunk):

matz	2009-09-28 12:09:16 +0900 (Mon, 28 Sep 2009)

  New Revision: 25129

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

  Log:


  Modified files:
    trunk/method.h
    trunk/proc.c
    trunk/test/ruby/test_object.rb
    trunk/vm_eval.c
    trunk/vm_insnhelper.c
    trunk/vm_method.c

Index: method.h
===================================================================
--- method.h	(revision 25128)
+++ method.h	(revision 25129)
@@ -39,7 +39,8 @@
     VM_METHOD_TYPE_ZSUPER,
     VM_METHOD_TYPE_UNDEF,
     VM_METHOD_TYPE_NOTIMPLEMENTED,
-    VM_METHOD_TYPE_OPTIMIZED /* Kernel#send, Proc#call, etc */
+    VM_METHOD_TYPE_OPTIMIZED, /* Kernel#send, Proc#call, etc */
+    VM_METHOD_TYPE_MISSING,   /* wrapper for method_missing(id) */
 } rb_method_type_t;
 
 typedef struct rb_method_cfunc_struct {
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 25128)
+++ vm_eval.c	(revision 25129)
@@ -110,6 +110,14 @@
 	if (!(def = me->def)) return Qnil;
 	goto again;
       }
+      case VM_METHOD_TYPE_MISSING: {
+	VALUE new_args = rb_ary_new4(argc, argv);
+
+	RB_GC_GUARD(new_args);
+	rb_ary_unshift(new_args, ID2SYM(id));
+	return rb_funcall2(recv, rb_intern("method_missing"),
+			   argc+1, RARRAY_PTR(new_args));
+      }
       case VM_METHOD_TYPE_OPTIMIZED: {
 	switch (def->body.optimize_type) {
 	  case OPTIMIZED_METHOD_TYPE_SEND:
Index: proc.c
===================================================================
--- proc.c	(revision 25128)
+++ proc.c	(revision 25129)
@@ -884,36 +884,36 @@
 }
 
 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;
     VALUE rclass = klass;
     ID rid = id;
     struct METHOD *data;
-    rb_method_entry_t *me;
-    rb_method_definition_t *def;
+    rb_method_entry_t *me, meb;
+    rb_method_definition_t *def = 0;
 
   again:
-    me = rb_method_entry(klass, id);
+     me = rb_method_entry(klass, id);
     if (UNDEFINED_METHOD_ENTRY_P(me)) {
 	ID rmiss = rb_intern("respond_to_missing?");
 	VALUE sym = ID2SYM(id);
 
 	if (obj != Qundef && !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));
+		def = ALLOC(rb_method_definition_t);
+		def->type = VM_METHOD_TYPE_MISSING;
+		def->original_id = id;
+		def->alias_count = 0;
+
+		meb.flag = 0;
+		meb.called_id = id;
+		meb.klass = klass;
+		meb.def = def;
+		me = &meb;
+		def = 0;
+
+		goto gen_method;
 	    }
 	}
 	rb_print_undef(klass, id, 0);
@@ -922,7 +922,7 @@
     if (scope && (me->flag & NOEX_MASK) != NOEX_PUBLIC) {
 	rb_print_undef(rclass, def->original_id, (int)(me->flag & NOEX_MASK));
     }
-    if (def->type == VM_METHOD_TYPE_ZSUPER) {
+    if (def && def->type == VM_METHOD_TYPE_ZSUPER) {
 	klass = RCLASS_SUPER(me->klass);
 	id = def->original_id;
 	goto again;
@@ -939,6 +939,7 @@
 	klass = RBASIC(klass)->klass;
     }
 
+  gen_method:
     method = TypedData_Make_Struct(mclass, struct METHOD, &method_data_type, data);
 
     data->recv = obj;
@@ -1552,6 +1553,8 @@
       case VM_METHOD_TYPE_UNDEF:
       case VM_METHOD_TYPE_NOTIMPLEMENTED:
 	return 0;
+      case VM_METHOD_TYPE_MISSING:
+	return -1;
       case VM_METHOD_TYPE_OPTIMIZED: {
 	switch (def->body.optimize_type) {
 	  case OPTIMIZED_METHOD_TYPE_SEND:
Index: vm_method.c
===================================================================
--- vm_method.c	(revision 25128)
+++ vm_method.c	(revision 25129)
@@ -810,6 +810,8 @@
 	return d1->body.attr_id == d2->body.attr_id;
       case VM_METHOD_TYPE_BMETHOD:
 	return RTEST(rb_equal(d1->body.proc, d2->body.proc));
+      case VM_METHOD_TYPE_MISSING:
+	return d1->original_id == d2->original_id;
       case VM_METHOD_TYPE_ZSUPER:
       case VM_METHOD_TYPE_NOTIMPLEMENTED:
       case VM_METHOD_TYPE_UNDEF:
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 25128)
+++ vm_insnhelper.c	(revision 25129)
@@ -527,6 +527,14 @@
 		cfp->sp -= 1;
 		break;
 	      }
+	      case VM_METHOD_TYPE_MISSING:{
+		VALUE *argv = ALLOCA_N(VALUE, num+1);
+		argv[0] = ID2SYM(me->def->original_id);
+		MEMCPY(argv+1, cfp->sp - num, VALUE, num);
+		cfp->sp += - num - 1;
+		val = rb_funcall2(recv, rb_intern("method_missing"), num+1, argv);
+		break;
+	      }
 	      case VM_METHOD_TYPE_BMETHOD:{
 		VALUE *argv = ALLOCA_N(VALUE, num);
 		MEMCPY(argv, cfp->sp - num, VALUE, num);
Index: test/ruby/test_object.rb
===================================================================
--- test/ruby/test_object.rb	(revision 25128)
+++ test/ruby/test_object.rb	(revision 25129)
@@ -333,9 +333,12 @@
     end
 
     foobar = foo.method(:foobar)
+    assert_equal(-1, foobar.arity);
     assert_equal([:foo], foobar.call);
     assert_equal([:foo, 1], foobar.call(1));
     assert_equal([:foo, 1, 2, 3, 4, 5], foobar.call(1, 2, 3, 4, 5));
+    assert_equal(foobar, foo.method(:foobar))
+    assert_not_equal(foobar, c.new.method(:foobar))
 
     c = Class.new(c)
     assert_equal(false, c.method_defined?(:foobar))

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

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