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

ruby-changes:24523

From: nobu <ko1@a...>
Date: Mon, 30 Jul 2012 14:24:34 +0900 (JST)
Subject: [ruby-changes:24523] nobu:r36574 (trunk): variable.c: tmp_classpath

nobu	2012-07-30 14:24:24 +0900 (Mon, 30 Jul 2012)

  New Revision: 36574

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

  Log:
    variable.c: tmp_classpath
    
    * variable.c: store anonymous class path in tmp_classpath but not in
      classpath.  [ruby-core:42865][Bug #6078]

  Modified files:
    trunk/ChangeLog
    trunk/test/ruby/test_module.rb
    trunk/variable.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 36573)
+++ ChangeLog	(revision 36574)
@@ -1,3 +1,8 @@
+Mon Jul 30 14:24:20 2012  Nobuyoshi Nakada  <nobu@r...>
+
+	* variable.c: store anonymous class path in tmp_classpath but not in
+	  classpath.  [ruby-core:42865][Bug #6078]
+
 Mon Jul 30 13:11:54 2012  Nobuyoshi Nakada  <nobu@r...>
 
 	* configure.in (DLDFLAGS): on Darwin, deprecate -flat_namespace to get
Index: variable.c
===================================================================
--- variable.c	(revision 36573)
+++ variable.c	(revision 36574)
@@ -35,7 +35,7 @@
 }
 
 struct fc_result {
-    ID name;
+    ID name, preferred;
     VALUE klass;
     VALUE path;
     VALUE track;
@@ -78,7 +78,7 @@
     VALUE value = ce->value;
     if (!rb_is_const_id(key)) return ST_CONTINUE;
 
-    if (value == res->klass) {
+    if (value == res->klass && (!res->preferred || key == res->preferred)) {
 	res->path = fc_path(res, key);
 	return ST_STOP;
     }
@@ -95,6 +95,7 @@
 	    }
 
 	    arg.name = key;
+	    arg.preferred = res->preferred;
 	    arg.path = 0;
 	    arg.klass = res->klass;
 	    arg.track = value;
@@ -110,10 +111,12 @@
 }
 
 static VALUE
-find_class_path(VALUE klass)
+find_class_path(VALUE klass, ID preferred)
 {
     struct fc_result arg;
 
+  find:
+    arg.preferred = preferred;
     arg.name = 0;
     arg.path = 0;
     arg.klass = klass;
@@ -134,6 +137,10 @@
 	st_delete(RCLASS_IV_TBL(klass), &tmp, 0);
 	return arg.path;
     }
+    if (preferred) {
+	preferred = 0;
+	goto find;
+    }
     return Qnil;
 }
 
@@ -147,9 +154,14 @@
     if (RCLASS_IV_TBL(klass)) {
 	if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classpath, &n)) {
 	    if (!st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classid, &n)) {
-		return find_class_path(klass);
+		return find_class_path(klass, (ID)0);
 	    }
-	    path = rb_str_dup(rb_id2str(SYM2ID((VALUE)n)));
+	    path = find_class_path(klass, SYM2ID(n));
+	    if (NIL_P(path)) {
+		path = rb_str_dup(rb_id2str(SYM2ID((VALUE)n)));
+		OBJ_FREEZE(path);
+		return path;
+	    }
 	    OBJ_FREEZE(path);
 	    st_insert(RCLASS_IV_TBL(klass), (st_data_t)classpath, (st_data_t)path);
 	    n = classid;
@@ -163,7 +175,7 @@
 	}
 	return path;
     }
-    return find_class_path(klass);
+    return find_class_path(klass, (ID)0);
 }
 
 /*
@@ -182,15 +194,19 @@
     return path;
 }
 
-VALUE
-rb_class_path(VALUE klass)
+static VALUE
+rb_tmp_class_path(VALUE klass, int *permanent)
 {
     VALUE path = classname(klass);
     st_data_t n = (st_data_t)path;
 
-    if (!NIL_P(path)) return path;
+    if (!NIL_P(path)) {
+	*permanent = 1;
+	return path;
+    }
     if (RCLASS_IV_TBL(klass) && st_lookup(RCLASS_IV_TBL(klass),
 					  (st_data_t)tmp_classpath, &n)) {
+	*permanent = 0;
 	return (VALUE)n;
     }
     else {
@@ -207,11 +223,19 @@
 	path = rb_sprintf("#<%s:%p>", s, (void*)klass);
 	OBJ_FREEZE(path);
 	rb_ivar_set(klass, tmp_classpath, path);
+	*permanent = 0;
 
 	return path;
     }
 }
 
+VALUE
+rb_class_path(VALUE klass)
+{
+    int permanent;
+    return rb_tmp_class_path(klass, &permanent);
+}
+
 void
 rb_set_class_path_string(VALUE klass, VALUE under, VALUE name)
 {
@@ -221,10 +245,12 @@
 	str = rb_str_new_frozen(name);
     }
     else {
-	str = rb_str_dup(rb_class_path(under));
+	int permanent;
+	str = rb_str_dup(rb_tmp_class_path(under, &permanent));
 	rb_str_cat2(str, "::");
 	rb_str_append(str, name);
 	OBJ_FREEZE(str);
+	if (!permanent) return;
     }
     rb_ivar_set(klass, classpath, str);
 }
@@ -233,16 +259,18 @@
 rb_set_class_path(VALUE klass, VALUE under, const char *name)
 {
     VALUE str;
+    int permanent = 1;
 
     if (under == rb_cObject) {
 	str = rb_str_new2(name);
     }
     else {
-	str = rb_str_dup(rb_class_path(under));
+	str = rb_str_dup(rb_tmp_class_path(under, &permanent));
 	rb_str_cat2(str, "::");
 	rb_str_cat2(str, name);
     }
     OBJ_FREEZE(str);
+    if (!permanent) return;
     rb_ivar_set(klass, classpath, str);
 }
 
Index: test/ruby/test_module.rb
===================================================================
--- test/ruby/test_module.rb	(revision 36573)
+++ test/ruby/test_module.rb	(revision 36574)
@@ -363,6 +363,23 @@
     assert_equal("TestModule::User",   User.name)
   end
 
+  def test_classpath
+    m = Module.new
+    n = Module.new
+    m.const_set(:N, n)
+    assert_nil(m.name)
+    assert_nil(n.name)
+    assert_equal([:N], m.constants)
+    m.module_eval("module O end")
+    assert_equal([:N, :O], m.constants)
+    assert_nil(m::N.name)
+    assert_match(/\A(?:#<Module:.*>::)?O\z/, m::O.name)
+    self.class.const_set(:M, m)
+    prefix = self.class.name + "::M::"
+    assert_equal(prefix+"N", m.const_get(:N).name)
+    assert_equal(prefix+"O", m.const_get(:O).name)
+  end
+
   def test_private_class_method
     assert_raise(ExpectedException) { AClass.cm1 }
     assert_raise(ExpectedException) { AClass.cm3 }

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

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