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

ruby-changes:12089

From: yugui <ko1@a...>
Date: Sat, 20 Jun 2009 18:07:56 +0900 (JST)
Subject: [ruby-changes:12089] Ruby:r23759 (ruby_1_9_1): merges r23557 and r23563 from trunk into ruby_1_9_1.

yugui	2009-06-20 18:06:35 +0900 (Sat, 20 Jun 2009)

  New Revision: 23759

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

  Log:
    merges r23557 and r23563 from trunk into ruby_1_9_1.
    --
    * thread.c (rb_exec_recursive_paired): new function for proper
      handling of recursive arrays.  [EXPERIMENTAL] [ruby-core:23402]
    * array.c (rb_ary_equal, rb_ary_eql, rb_ary_cmp): use above.
    
    * hash.c (hash_equal): ditto.
    --
    * test/ruby/test_hash.rb (TestHash::test_equal2): recursive hashes
      are handled properly now. ref: [ruby-core:23402]
    
    * test/ruby/test_m17n.rb (TestM17N#test_sprintf_p): test fixed

  Modified files:
    branches/ruby_1_9_1/ChangeLog
    branches/ruby_1_9_1/array.c
    branches/ruby_1_9_1/hash.c
    branches/ruby_1_9_1/include/ruby/intern.h
    branches/ruby_1_9_1/test/ruby/test_hash.rb
    branches/ruby_1_9_1/test/ruby/test_m17n.rb
    branches/ruby_1_9_1/thread.c
    branches/ruby_1_9_1/version.h

Index: ruby_1_9_1/array.c
===================================================================
--- ruby_1_9_1/array.c	(revision 23758)
+++ ruby_1_9_1/array.c	(revision 23759)
@@ -2656,7 +2656,7 @@
 {
     long i;
 
-    if (recur) return Qfalse;
+    if (recur) return Qtrue; /* Subtle! */
     for (i=0; i<RARRAY_LEN(ary1); i++) {
 	if (!rb_equal(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
 	    return Qfalse;
@@ -2689,7 +2689,7 @@
 	return rb_equal(ary2, ary1);
     }
     if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
-    return rb_exec_recursive(recursive_equal, ary1, ary2);
+    return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
 }
 
 static VALUE
@@ -2697,7 +2697,7 @@
 {
     long i;
 
-    if (recur) return Qfalse;
+    if (recur) return Qtrue; /* Subtle! */
     for (i=0; i<RARRAY_LEN(ary1); i++) {
 	if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
 	    return Qfalse;
@@ -2719,7 +2719,7 @@
     if (ary1 == ary2) return Qtrue;
     if (TYPE(ary2) != T_ARRAY) return Qfalse;
     if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
-    return rb_exec_recursive(recursive_eql, ary1, ary2);
+    return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
 }
 
 static VALUE
@@ -2786,7 +2786,7 @@
 {
     long i, len;
 
-    if (recur) return Qnil;
+    if (recur) return Qundef;	/* Subtle! */
     len = RARRAY_LEN(ary1);
     if (len > RARRAY_LEN(ary2)) {
 	len = RARRAY_LEN(ary2);
@@ -2828,7 +2828,7 @@
 
     ary2 = to_ary(ary2);
     if (ary1 == ary2) return INT2FIX(0);
-    v = rb_exec_recursive(recursive_cmp, ary1, ary2);
+    v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2);
     if (v != Qundef) return v;
     len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
     if (len == 0) return INT2FIX(0);
Index: ruby_1_9_1/include/ruby/intern.h
===================================================================
--- ruby_1_9_1/include/ruby/intern.h	(revision 23758)
+++ ruby_1_9_1/include/ruby/intern.h	(revision 23759)
@@ -335,6 +335,7 @@
 void rb_thread_atfork(void);
 void rb_thread_atfork_before_exec(void);
 VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE);
+VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE,VALUE);
 /* file.c */
 VALUE rb_file_s_expand_path(int, VALUE *);
 VALUE rb_file_expand_path(VALUE, VALUE);
Index: ruby_1_9_1/ChangeLog
===================================================================
--- ruby_1_9_1/ChangeLog	(revision 23758)
+++ ruby_1_9_1/ChangeLog	(revision 23759)
@@ -1,3 +1,19 @@
+Mon May 25 06:25:38 2009  Yukihiro Matsumoto  <matz@r...>
+
+	* test/ruby/test_hash.rb (TestHash::test_equal2): recursive hashes
+	  are handled properly now. ref: [ruby-core:23402]
+
+	* test/ruby/test_m17n.rb (TestM17N#test_sprintf_p): test fixed
+
+Sun May 24 22:48:17 2009  Nobuyoshi Nakada  <nobu@r...>
+
+	* thread.c (rb_exec_recursive_paired): new function for proper
+	  handling of recursive arrays.  [EXPERIMENTAL] [ruby-core:23402]
+
+	* array.c (rb_ary_equal, rb_ary_eql, rb_ary_cmp): use above.
+
+	* hash.c (hash_equal): ditto.
+
 Sun May 24 22:39:33 2009  Nobuyoshi Nakada  <nobu@r...>
 
 	* error.c (syserr_initialize): errno is int.
Index: ruby_1_9_1/thread.c
===================================================================
--- ruby_1_9_1/thread.c	(revision 23758)
+++ ruby_1_9_1/thread.c	(revision 23759)
@@ -3279,26 +3279,39 @@
 static ID recursive_key;
 
 static VALUE
-recursive_check(VALUE hash, VALUE obj)
+recursive_check(VALUE hash, VALUE obj, VALUE paired_obj)
 {
     if (NIL_P(hash) || TYPE(hash) != T_HASH) {
 	return Qfalse;
     }
     else {
-	VALUE list = rb_hash_aref(hash, ID2SYM(rb_frame_this_func()));
+	VALUE sym = ID2SYM(rb_frame_this_func());
+	VALUE list = rb_hash_aref(hash, sym);
+	VALUE pair_list;
 
 	if (NIL_P(list) || TYPE(list) != T_HASH)
 	    return Qfalse;
-	if (NIL_P(rb_hash_lookup(list, obj)))
+	pair_list = rb_hash_lookup2(list, obj, Qundef);
+	if (pair_list == Qundef)
 	    return Qfalse;
+	if (paired_obj) {
+	    if (TYPE(pair_list) != T_HASH) {
+		if (pair_list != paired_obj)
+		    return Qfalse;
+	    }
+	    else {
+		if (NIL_P(rb_hash_lookup(pair_list, paired_obj)))
+		    return Qfalse;
+	    }
+	}
 	return Qtrue;
     }
 }
 
 static VALUE
-recursive_push(VALUE hash, VALUE obj)
+recursive_push(VALUE hash, VALUE obj, VALUE paired_obj)
 {
-    VALUE list, sym;
+    VALUE list, sym, pair_list;
 
     sym = ID2SYM(rb_frame_this_func());
     if (NIL_P(hash) || TYPE(hash) != T_HASH) {
@@ -3313,61 +3326,99 @@
 	list = rb_hash_new();
 	rb_hash_aset(hash, sym, list);
     }
-    rb_hash_aset(list, obj, Qtrue);
+    if (!paired_obj) {
+	rb_hash_aset(list, obj, Qtrue);
+    }
+    else if ((pair_list = rb_hash_lookup2(list, obj, Qundef)) == Qundef) {
+	rb_hash_aset(list, obj, paired_obj);
+    }
+    else {
+	if (TYPE(pair_list) != T_HASH){
+	    VALUE other_paired_obj = pair_list;
+	    pair_list = rb_hash_new();
+	    rb_hash_aset(pair_list, other_paired_obj, Qtrue);
+	    rb_hash_aset(list, obj, pair_list);
+	}
+	rb_hash_aset(pair_list, paired_obj, Qtrue);
+    }
     return hash;
 }
 
 static void
-recursive_pop(VALUE hash, VALUE obj)
+recursive_pop(VALUE hash, VALUE obj, VALUE paired_obj)
 {
-    VALUE list, sym;
+    VALUE list, sym, pair_list, symname, thrname;
 
     sym = ID2SYM(rb_frame_this_func());
     if (NIL_P(hash) || TYPE(hash) != T_HASH) {
-	VALUE symname;
-	VALUE thrname;
 	symname = rb_inspect(sym);
 	thrname = rb_inspect(rb_thread_current());
-
 	rb_raise(rb_eTypeError, "invalid inspect_tbl hash for %s in %s",
 		 StringValuePtr(symname), StringValuePtr(thrname));
     }
     list = rb_hash_aref(hash, sym);
     if (NIL_P(list) || TYPE(list) != T_HASH) {
-	VALUE symname = rb_inspect(sym);
-	VALUE thrname = rb_inspect(rb_thread_current());
+	symname = rb_inspect(sym);
+	thrname = rb_inspect(rb_thread_current());
 	rb_raise(rb_eTypeError, "invalid inspect_tbl list for %s in %s",
 		 StringValuePtr(symname), StringValuePtr(thrname));
     }
+    if (paired_obj) {
+	pair_list = rb_hash_lookup2(list, obj, Qundef);
+	if (pair_list == Qundef) {
+	    symname = rb_inspect(sym);
+	    thrname = rb_inspect(rb_thread_current());
+	    rb_raise(rb_eTypeError, "invalid inspect_tbl pair_list for %s in %s",
+		     StringValuePtr(symname), StringValuePtr(thrname));
+	}
+	if (TYPE(pair_list) == T_HASH) {
+	    rb_hash_delete(pair_list, paired_obj);
+	    if (!RHASH_EMPTY_P(pair_list)) {
+		return; /* keep hash until is empty */
+	    }
+	}
+    }
     rb_hash_delete(list, obj);
 }
 
-VALUE
-rb_exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
+static VALUE
+exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE arg)
 {
     VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
     VALUE objid = rb_obj_id(obj);
 
-    if (recursive_check(hash, objid)) {
+    if (recursive_check(hash, objid, pairid)) {
 	return (*func) (obj, arg, Qtrue);
     }
     else {
 	VALUE result = Qundef;
 	int state;
 
-	hash = recursive_push(hash, objid);
+	hash = recursive_push(hash, objid, pairid);
 	PUSH_TAG();
 	if ((state = EXEC_TAG()) == 0) {
 	    result = (*func) (obj, arg, Qfalse);
 	}
 	POP_TAG();
-	recursive_pop(hash, objid);
+	recursive_pop(hash, objid, pairid);
 	if (state)
 	    JUMP_TAG(state);
 	return result;
     }
 }
 
+VALUE
+rb_exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
+{
+    return exec_recursive(func, obj, 0, arg);
+}
+
+VALUE
+rb_exec_recursive_paired(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE paired_obj, VALUE arg)
+{
+    return exec_recursive(func, obj, rb_obj_id(paired_obj), arg);
+}
+
 /* tracer */
 
 static rb_event_hook_t *
Index: ruby_1_9_1/hash.c
===================================================================
--- ruby_1_9_1/hash.c	(revision 23758)
+++ ruby_1_9_1/hash.c	(revision 23759)
@@ -1428,7 +1428,7 @@
 {
     struct equal_data *data;
 
-    if (recur) return Qfalse;
+    if (recur) return Qtrue;	/* Subtle! */
     data = (struct equal_data*)dt;
     data->result = Qtrue;
     rb_hash_foreach(hash, eql_i, (st_data_t)data);
@@ -1465,7 +1465,7 @@
 
     data.tbl = RHASH(hash2)->ntbl;
     data.eql = eql;
-    return rb_exec_recursive(recursive_eql, hash1, (VALUE)&data);
+    return rb_exec_recursive_paired(recursive_eql, hash1, hash2, (VALUE)&data);
 }
 
 /*
Index: ruby_1_9_1/version.h
===================================================================
--- ruby_1_9_1/version.h	(revision 23758)
+++ ruby_1_9_1/version.h	(revision 23759)
@@ -1,6 +1,6 @@
 #define RUBY_VERSION "1.9.1"
 #define RUBY_RELEASE_DATE "2009-05-22"
-#define RUBY_PATCHLEVEL 157
+#define RUBY_PATCHLEVEL 158
 #define RUBY_VERSION_MAJOR 1
 #define RUBY_VERSION_MINOR 9
 #define RUBY_VERSION_TEENY 1
Index: ruby_1_9_1/test/ruby/test_m17n.rb
===================================================================
--- ruby_1_9_1/test/ruby/test_m17n.rb	(revision 23758)
+++ ruby_1_9_1/test/ruby/test_m17n.rb	(revision 23759)
@@ -770,7 +770,7 @@
     #assert_strenc("\"\xC2\xA1\"", 'Windows-31J', s("%p") % s("\xc2\xa1"))
     assert_strenc("\"\xC2\xA1\"", 'UTF-8', u("%p") % u("\xc2\xa1"))
 
-    assert_strenc('"\xC2\xA1"', 'US-ASCII', "%10p" % a("\xc2\xa1"))
+    assert_strenc('"\xC2\xA1"', 'ASCII-8BIT', "%10p" % a("\xc2\xa1"))
     assert_strenc("       \"\xC2\xA1\"", 'EUC-JP', "%10p" % e("\xc2\xa1"))
     #assert_strenc("       \"\xC2\xA1\"", 'Windows-31J', "%10p" % s("\xc2\xa1"))
     assert_strenc("       \"\xC2\xA1\"", 'UTF-8', "%10p" % u("\xc2\xa1"))
Index: ruby_1_9_1/test/ruby/test_hash.rb
===================================================================
--- ruby_1_9_1/test/ruby/test_hash.rb	(revision 23758)
+++ ruby_1_9_1/test/ruby/test_hash.rb	(revision 23759)
@@ -770,7 +770,9 @@
 
     h1 = {}; h1[h1] = h1; h1.rehash
     h2 = {}; h2[h2] = h2; h2.rehash
-    assert(h1 != h2)
+    # assert(h1 != h2)
+    # recursive hashes are handled properly now. [ruby-core:23402]
+    assert(h1 == h2)
   end
 
   def test_eql

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

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