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

ruby-changes:32835

From: nagachika <ko1@a...>
Date: Wed, 12 Feb 2014 03:31:00 +0900 (JST)
Subject: [ruby-changes:32835] nagachika:r44911 (ruby_2_0_0): merge revision(s) r42479, r42490, r42509, r43083, r43084, r43085: [Backport #8756] [Backport #9248]

nagachika	2014-02-11 23:55:00 +0900 (Tue, 11 Feb 2014)

  New Revision: 44911

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

  Log:
    merge revision(s) r42479,r42490,r42509,r43083,r43084,r43085: [Backport #8756] [Backport #9248]
    
    * parse.y (rb_enc_symname_type): allow ID_ATTRSET for ID_INSTANCE,
      ID_GLOBAL, ID_CLASS, ID_JUNK too.  [Bug #8756]
    
    * parse.y (rb_id_attrset): fix inconsistency with literals, allow
      ID_ATTRSET and return it itself, but ID_JUNK cannot make ID_ATTRSET.
      and raise a NameError instead of rb_bug() for invalid argument.
    
    * parse.y (rb_id_attrset, intern_str): allow junk attrset ID for
      Struct.
    
    * parse.y (rb_id_attrset): check if the argument is valid type as an
      attribute.
    
    * parse.y (rb_id_attrset): allow other than ID_ATTRSET.
    
    * parse.y (intern_str): ditto.  try stem ID for ID_INSTANCE,
      ID_GLOBAL, ID_CLASS, ID_JUNK too.  [Bug #8756]

  Modified directories:
    branches/ruby_2_0_0/
  Modified files:
    branches/ruby_2_0_0/ChangeLog
    branches/ruby_2_0_0/ext/-test-/symbol/type.c
    branches/ruby_2_0_0/parse.y
    branches/ruby_2_0_0/test/-ext-/symbol/test_type.rb
    branches/ruby_2_0_0/test/ruby/test_struct.rb
    branches/ruby_2_0_0/version.h
Index: ruby_2_0_0/ChangeLog
===================================================================
--- ruby_2_0_0/ChangeLog	(revision 44910)
+++ ruby_2_0_0/ChangeLog	(revision 44911)
@@ -1,3 +1,35 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ChangeLog#L1
+Tue Feb 11 23:21:02 2014  CHIKANAGA Tomoyuki  <nagachika@r...>
+
+	* test/ruby/test_struct.rb (test_struct_question_mark): add a testcase
+	  for Struct attribute with question mark. the patch was originally
+	  written by Eric Wong [ruby-core:59095] [Backport #9248]
+
+Tue Feb 11 23:21:02 2014  Nobuyoshi Nakada  <nobu@r...>
+
+	* parse.y (rb_id_attrset, intern_str): allow junk attrset ID for
+	  Struct.
+
+	* parse.y (rb_id_attrset): fix inconsistency with literals, allow
+	  ID_ATTRSET and return it itself, but ID_JUNK cannot make ID_ATTRSET.
+	  and raise a NameError instead of rb_bug() for invalid argument.
+
+Tue Feb 11 23:21:02 2014  Nobuyoshi Nakada  <nobu@r...>
+
+	* parse.y (rb_enc_symname_type): allow ID_ATTRSET for ID_INSTANCE,
+	  ID_GLOBAL, ID_CLASS, ID_JUNK too.  [Bug #8756]
+
+Tue Feb 11 23:21:02 2014  Nobuyoshi Nakada  <nobu@r...>
+
+	* parse.y (rb_id_attrset): allow other than ID_ATTRSET.
+
+	* parse.y (intern_str): ditto.  try stem ID for ID_INSTANCE,
+	  ID_GLOBAL, ID_CLASS, ID_JUNK too.  [Bug #8756]
+
+Tue Feb 11 23:21:02 2014  Nobuyoshi Nakada  <nobu@r...>
+
+	* parse.y (rb_id_attrset): check if the argument is valid type as an
+	  attribute.
+
 Tue Feb 11 00:26:19 2014  Nobuyoshi Nakada  <nobu@r...>
 
 	* file.c (GetLastError): already defined in windows.h on nowadays
Index: ruby_2_0_0/parse.y
===================================================================
--- ruby_2_0_0/parse.y	(revision 44910)
+++ ruby_2_0_0/parse.y	(revision 44911)
@@ -8678,9 +8678,41 @@ block_dup_check_gen(struct parser_params https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/parse.y#L8678
     }
 }
 
+static const char id_type_names[][9] = {
+    "LOCAL",
+    "INSTANCE",
+    "",				/* INSTANCE2 */
+    "GLOBAL",
+    "ATTRSET",
+    "CONST",
+    "CLASS",
+    "JUNK",
+};
+
 ID
 rb_id_attrset(ID id)
 {
+    if (!is_notop_id(id)) {
+	switch (id) {
+	  case tAREF: case tASET:
+	    return tASET;	/* only exception */
+	}
+	rb_name_error(id, "cannot make operator ID :%s attrset", rb_id2name(id));
+    }
+    else {
+	int scope = (int)(id & ID_SCOPE_MASK);
+	switch (scope) {
+	  case ID_LOCAL: case ID_INSTANCE: case ID_GLOBAL:
+	  case ID_CONST: case ID_CLASS: case ID_JUNK:
+	    break;
+	  case ID_ATTRSET:
+	    return id;
+	  default:
+	    rb_name_error(id, "cannot make %s ID %+"PRIsVALUE" attrset",
+			  id_type_names[scope], ID2SYM(id));
+
+	}
+    }
     id &= ~ID_SCOPE_MASK;
     id |= ID_ATTRSET;
     return id;
@@ -10062,8 +10094,11 @@ rb_enc_symname_p(const char *name, rb_en https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/parse.y#L10094
     return rb_enc_symname2_p(name, strlen(name), enc);
 }
 
+#define IDSET_ATTRSET_FOR_SYNTAX ((1U<<ID_LOCAL)|(1U<<ID_CONST))
+#define IDSET_ATTRSET_FOR_INTERN (~(~0U<<ID_SCOPE_MASK) & ~(1U<<ID_ATTRSET))
+
 static int
-rb_enc_symname_type(const char *name, long len, rb_encoding *enc)
+rb_enc_symname_type(const char *name, long len, rb_encoding *enc, unsigned int allowed_atttset)
 {
     const char *m = name;
     const char *e = m + len;
@@ -10148,7 +10183,7 @@ rb_enc_symname_type(const char *name, lo https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/parse.y#L10183
 	    ++m;
 	    break;
 	  case '=':
-	    if (type != ID_CONST && type != ID_LOCAL) return -1;
+	    if (!(allowed_atttset & (1U << type))) return -1;
 	    type = ID_ATTRSET;
 	    ++m;
 	    break;
@@ -10161,15 +10196,15 @@ rb_enc_symname_type(const char *name, lo https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/parse.y#L10196
 int
 rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
 {
-    return rb_enc_symname_type(name, len, enc) != -1;
+    return rb_enc_symname_type(name, len, enc, IDSET_ATTRSET_FOR_SYNTAX) != -1;
 }
 
 static int
-rb_str_symname_type(VALUE name)
+rb_str_symname_type(VALUE name, unsigned int allowed_atttset)
 {
     const char *ptr = StringValuePtr(name);
     long len = RSTRING_LEN(name);
-    int type = rb_enc_symname_type(ptr, len, rb_enc_get(name));
+    int type = rb_enc_symname_type(ptr, len, rb_enc_get(name), allowed_atttset);
     RB_GC_GUARD(name);
     return type;
 }
@@ -10294,26 +10329,27 @@ intern_str(VALUE str) https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/parse.y#L10329
 		}
 	    }
 	}
-
-	if (m[last] == '=') {
-	    /* attribute assignment */
-	    if (!rb_enc_symname2_p(name, last, enc))
-		goto junk;
-	    id = rb_intern3(name, last, enc);
-	    if (id > tLAST_OP_ID && !is_attrset_id(id)) {
-		enc = rb_enc_get(rb_id2str(id));
-		id = rb_id_attrset(id);
-		goto id_register;
-	    }
-	    id = ID_ATTRSET;
+	break;
+    }
+    if (name[last] == '=') {
+	/* attribute assignment */
+	if (last > 1 && name[last-1] == '=')
+	    goto junk;
+	id = rb_intern3(name, last, enc);
+	if (id > tLAST_OP_ID && !is_attrset_id(id)) {
+	    enc = rb_enc_get(rb_id2str(id));
+	    id = rb_id_attrset(id);
+	    goto id_register;
 	}
-	else if (rb_enc_isupper(m[0], enc)) {
+	id = ID_ATTRSET;
+    }
+    else if (id == 0) {
+	if (rb_enc_isupper(m[0], enc)) {
 	    id = ID_CONST;
-        }
+	}
 	else {
 	    id = ID_LOCAL;
 	}
-	break;
     }
     if (!rb_enc_isdigit(*m, enc)) {
 	while (m <= name + last && is_identchar(m, e, enc)) {
@@ -10325,7 +10361,7 @@ intern_str(VALUE str) https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/parse.y#L10361
 	    }
 	}
     }
-    if (m - name < len) id = ID_JUNK;
+    if (id != ID_ATTRSET && m - name < len) id = ID_JUNK;
     if (sym_check_asciionly(str)) symenc = rb_usascii_encoding();
   new_id:
     if (symenc != enc) rb_enc_associate(str, symenc);
@@ -10408,16 +10444,21 @@ rb_id2str(ID id) https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/parse.y#L10444
     }
 
     if (is_attrset_id(id)) {
-	ID id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
+	ID id_stem = (id & ~ID_SCOPE_MASK);
 	VALUE str;
 
-	while (!(str = rb_id2str(id2))) {
-	    if (!is_local_id(id2)) return 0;
-	    id2 = (id & ~ID_SCOPE_MASK) | ID_CONST;
-	}
+	do {
+	    if (!!(str = rb_id2str(id_stem | ID_LOCAL))) break;
+	    if (!!(str = rb_id2str(id_stem | ID_CONST))) break;
+	    if (!!(str = rb_id2str(id_stem | ID_INSTANCE))) break;
+	    if (!!(str = rb_id2str(id_stem | ID_GLOBAL))) break;
+	    if (!!(str = rb_id2str(id_stem | ID_CLASS))) break;
+	    if (!!(str = rb_id2str(id_stem | ID_JUNK))) break;
+	    return 0;
+	} while (0);
 	str = rb_str_dup(str);
 	rb_str_cat(str, "=", 1);
-	rb_intern_str(str);
+	register_symid_str(id, str);
 	if (st_lookup(global_symbols.id_str, id, &data)) {
             VALUE str = (VALUE)data;
             if (RBASIC(str)->klass == 0)
@@ -10600,43 +10641,43 @@ rb_check_id_cstr(const char *ptr, long l https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/parse.y#L10641
 int
 rb_is_const_name(VALUE name)
 {
-    return rb_str_symname_type(name) == ID_CONST;
+    return rb_str_symname_type(name, 0) == ID_CONST;
 }
 
 int
 rb_is_class_name(VALUE name)
 {
-    return rb_str_symname_type(name) == ID_CLASS;
+    return rb_str_symname_type(name, 0) == ID_CLASS;
 }
 
 int
 rb_is_global_name(VALUE name)
 {
-    return rb_str_symname_type(name) == ID_GLOBAL;
+    return rb_str_symname_type(name, 0) == ID_GLOBAL;
 }
 
 int
 rb_is_instance_name(VALUE name)
 {
-    return rb_str_symname_type(name) == ID_INSTANCE;
+    return rb_str_symname_type(name, 0) == ID_INSTANCE;
 }
 
 int
 rb_is_attrset_name(VALUE name)
 {
-    return rb_str_symname_type(name) == ID_ATTRSET;
+    return rb_str_symname_type(name, IDSET_ATTRSET_FOR_INTERN) == ID_ATTRSET;
 }
 
 int
 rb_is_local_name(VALUE name)
 {
-    return rb_str_symname_type(name) == ID_LOCAL;
+    return rb_str_symname_type(name, 0) == ID_LOCAL;
 }
 
 int
 rb_is_method_name(VALUE name)
 {
-    switch (rb_str_symname_type(name)) {
+    switch (rb_str_symname_type(name, 0)) {
       case ID_LOCAL: case ID_ATTRSET: case ID_JUNK:
 	return TRUE;
     }
@@ -10646,7 +10687,7 @@ rb_is_method_name(VALUE name) https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/parse.y#L10687
 int
 rb_is_junk_name(VALUE name)
 {
-    return rb_str_symname_type(name) == -1;
+    return rb_str_symname_type(name, IDSET_ATTRSET_FOR_SYNTAX) == -1;
 }
 
 #endif /* !RIPPER */
Index: ruby_2_0_0/ext/-test-/symbol/type.c
===================================================================
--- ruby_2_0_0/ext/-test-/symbol/type.c	(revision 44910)
+++ ruby_2_0_0/ext/-test-/symbol/type.c	(revision 44911)
@@ -27,8 +27,17 @@ bug_sym_##type##_p(VALUE self, VALUE nam https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/ext/-test-/symbol/type.c#L27
 
 FOREACH_ID_TYPES(define_symbol_type_p)
 
+static VALUE
+bug_sym_attrset(VALUE self, VALUE name)
+{
+    ID id = rb_to_id(name);
+    id = rb_id_attrset(id);
+    return ID2SYM(id);
+}
+
 void
 Init_type(VALUE klass)
 {
-    FOREACH_ID_TYPES(declare_symbol_type_p)
+    FOREACH_ID_TYPES(declare_symbol_type_p);
+    rb_define_singleton_method(klass, "attrset", bug_sym_attrset, 1);
 }
Index: ruby_2_0_0/version.h
===================================================================
--- ruby_2_0_0/version.h	(revision 44910)
+++ ruby_2_0_0/version.h	(revision 44911)
@@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/version.h#L1
 #define RUBY_VERSION "2.0.0"
 #define RUBY_RELEASE_DATE "2014-02-11"
-#define RUBY_PATCHLEVEL 401
+#define RUBY_PATCHLEVEL 402
 
 #define RUBY_RELEASE_YEAR 2014
 #define RUBY_RELEASE_MONTH 2
Index: ruby_2_0_0/test/ruby/test_struct.rb
===================================================================
--- ruby_2_0_0/test/ruby/test_struct.rb	(revision 44910)
+++ ruby_2_0_0/test/ruby/test_struct.rb	(revision 44911)
@@ -142,7 +142,19 @@ class TestStruct < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/test/ruby/test_struct.rb#L142
 
     klass = Struct.new(:@a)
     o = klass.new(1)
+    assert_equal(1, o.__send__(:@a))
     assert_equal("#<struct :@a=1>", o.inspect)
+    o.__send__(:"@a=", 2)
+    assert_equal(2, o.__send__(:@a))
+    assert_equal("#<struct :@a=2>", o.inspect)
+    o.__send__("@a=", 3)
+    assert_equal(3, o.__send__(:@a))
+    assert_equal("#<struct :@a=3>", o.inspect)
+
+    methods = klass.instance_methods(false)
+    assert_equal([:@a, :"@a="].inspect, methods.inspect, '[Bug #8756]')
+    assert_include(methods, :@a)
+    assert_include(methods, :"@a=")
   end
 
   def test_init_copy
@@ -281,4 +293,10 @@ class TestStruct < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/test/ruby/test_struct.rb#L293
     o = klass.new(1, 2, 3, 4, 5, 6)
     assert_equal({a:1, b:2, c:3, d:4, e:5, f:6}, o.to_h)
   end
+
+  def test_struct_question_mark
+    bug9248 = '[ruby-core:59095]'
+    klass = Struct.new(:a?)
+    assert_include(klass.new.methods.inspect, ':a?', bug9248)
+  end
 end
Index: ruby_2_0_0/test/-ext-/symbol/test_type.rb
===================================================================
--- ruby_2_0_0/test/-ext-/symbol/test_type.rb	(revision 44910)
+++ ruby_2_0_0/test/-ext-/symbol/test_type.rb	(revision 44911)
@@ -82,15 +82,29 @@ module Test_Symbol https://github.com/ruby/ruby/blob/trunk/ruby_2_0_0/test/-ext-/symbol/test_type.rb#L82
       assert_symtype("@foo=", :attrset?)
       assert_symtype("@@foo=", :attrset?)
       assert_symtype("$foo=", :attrset?)
-      assert_not_symtype("0=", :attrset?)
-      assert_not_symtype("@=", :attrset?)
-      assert_not_symtype("@@=", :attrset?)
+      assert_symtype("0=", :attrset?)
+      assert_symtype("@=", :attrset?)
+      assert_symtype("@@=", :attrset?)
       assert_not_symtype("foo", :attrset?)
       assert_not_symtype("Foo", :attrset?)
       assert_not_symtype("@foo", :attrset?)
       assert_not_symtype("@@foo", :attrset?)
       assert_not_symtype("$foo", :attrset?)
       assert_not_symtype("[foo]", :attrset?)
+      assert_symtype("[foo]=", :attrset?)
+      assert_equal(:"foo=", Bug::Symbol.attrset("foo"))
+      assert_symtype(Bug::Symbol.attrset("foo"), :attrset?)
+      assert_equal(:"Foo=", Bug::Symbol.attrset("Foo"))
+      assert_symtype(Bug::Symbol.attrset("Foo"), :attrset?)
+      assert_equal(:"@foo=", Bug::Symbol.attrset("@foo"))
+      assert_symtype(Bug::Symbol.attrset("@foo"), :attrset?)
+      assert_equal(:"@@foo=", Bug::Symbol.attrset("@@foo"))
+      assert_symtype(Bug::Symbol.attrset("@@foo"), :attrset?)
+      assert_equal(:"$foo=", Bug::Symbol.attrset("$foo"))
+      assert_symtype(Bug::Symbol.attrset("$foo"), :attrset?)
+      assert_equal(:"[foo]=", Bug::Symbol.attrset("[foo]"))
+      assert_symtype(Bug::Symbol.attrset("[foo]"), :attrset?)
+      assert_equal(:[]=, Bug::Symbol.attrset(:[]))
     end
   end
 end

Property changes on: ruby_2_0_0
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /trunk:r42479,42490,42509,43083-43085


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

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