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

ruby-changes:34284

From: nobu <ko1@a...>
Date: Fri, 6 Jun 2014 17:07:33 +0900 (JST)
Subject: [ruby-changes:34284] nobu:r46365 (trunk): compile.c, parse.y: private op assign

nobu	2014-06-06 17:07:13 +0900 (Fri, 06 Jun 2014)

  New Revision: 46365

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

  Log:
    compile.c, parse.y: private op assign
    
    * compile.c (iseq_compile_each), parse.y (new_attr_op_assign_gen):
      allow op assign to a private attribute.
      [ruby-core:62949] [Bug #9907]

  Modified files:
    trunk/ChangeLog
    trunk/compile.c
    trunk/parse.y
    trunk/test/ruby/test_assignment.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 46364)
+++ ChangeLog	(revision 46365)
@@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Fri Jun  6 17:07:08 2014  Nobuyoshi Nakada  <nobu@r...>
+
+	* compile.c (iseq_compile_each), parse.y (new_attr_op_assign_gen):
+	  allow op assign to a private attribute.
+	  [ruby-core:62949] [Bug #9907]
+
 Fri Jun  6 13:39:32 2014  Nobuyoshi Nakada  <nobu@r...>
 
 	* io.c (io_setstrbuf, io_read): should not shorten the given buffer until
Index: compile.c
===================================================================
--- compile.c	(revision 46364)
+++ compile.c	(revision 46365)
@@ -265,6 +265,11 @@ r_value(VALUE value) https://github.com/ruby/ruby/blob/trunk/compile.c#L265
   (debug_compile("== " desc "\n", \
                  iseq_compile_each(iseq, (anchor), (node), (poped))))
 
+#define COMPILE_RECV(anchor, desc, node) \
+    (private_recv_p(node) ? \
+     (ADD_INSN(anchor, nd_line(node), putself), VM_CALL_FCALL) : \
+     (COMPILE(anchor, desc, node->nd_recv), 0))
+
 #define OPERAND_AT(insn, idx) \
   (((INSN*)(insn))->operands[(idx)])
 
@@ -3983,6 +3988,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L3988
 	DECL_ANCHOR(args);
 	VALUE argc;
 	VALUE flag = 0;
+	VALUE asgnflag = 0;
 	ID id = node->nd_mid;
 	int boff = 0;
 
@@ -4012,7 +4018,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L4018
 	if (!poped) {
 	    ADD_INSN(ret, line, putnil);
 	}
-	COMPILE(ret, "NODE_OP_ASGN1 recv", node->nd_recv);
+	asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN1 recv", node);
 	switch (nd_type(node->nd_args->nd_head)) {
 	  case NODE_ZARRAY:
 	    argc = INT2FIX(0);
@@ -4026,6 +4032,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L4032
 	}
 	ADD_INSN1(ret, line, dupn, FIXNUM_INC(argc, 1 + boff));
 	ADD_SEND_R(ret, line, ID2SYM(idAREF), argc, Qfalse, LONG2FIX(flag));
+	flag |= asgnflag;
 
 	if (id == 0 || id == 1) {
 	    /* 0: or, 1: and
@@ -4121,6 +4128,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L4128
       }
       case NODE_OP_ASGN2:{
 	ID atype = node->nd_next->nd_mid;
+	VALUE asgnflag;
 	LABEL *lfin = NEW_LABEL(line);
 	LABEL *lcfin = NEW_LABEL(line);
 	/*
@@ -4165,7 +4173,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L4173
 
 	*/
 
-	COMPILE(ret, "NODE_OP_ASGN2#recv", node->nd_recv);
+	asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN2#recv", node);
 	ADD_INSN(ret, line, dup);
 	ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_vid),
 		 INT2FIX(0));
@@ -4182,8 +4190,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L4190
 	    COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value);
 	    ADD_INSN(ret, line, swap);
 	    ADD_INSN1(ret, line, topn, INT2FIX(1));
-	    ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_aid),
-		     INT2FIX(1));
+	    ADD_SEND_R(ret, line, ID2SYM(node->nd_next->nd_aid),
+		       INT2FIX(1), Qfalse, INT2FIX(asgnflag));
 	    ADD_INSNL(ret, line, jump, lfin);
 
 	    ADD_LABEL(ret, lcfin);
@@ -4204,8 +4212,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L4212
 		ADD_INSN(ret, line, swap);
 		ADD_INSN1(ret, line, topn, INT2FIX(1));
 	    }
-	    ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_aid),
-		     INT2FIX(1));
+	    ADD_SEND_R(ret, line, ID2SYM(node->nd_next->nd_aid),
+		       INT2FIX(1), Qfalse, INT2FIX(asgnflag));
 	    ADD_INSN(ret, line, pop);
 	}
 	break;
@@ -5347,13 +5355,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ https://github.com/ruby/ruby/blob/trunk/compile.c#L5355
 	INIT_ANCHOR(args);
 	argc = setup_args(iseq, args, node->nd_args, &flag);
 
-	if (private_recv_p(node)) {
-	    flag |= VM_CALL_FCALL;
-	    ADD_INSN(recv, line, putself);
-	}
-	else {
-	    COMPILE(recv, "recv", node->nd_recv);
-	}
+	flag |= COMPILE_RECV(recv, "recv", node);
 
 	debugp_param("argc", argc);
 	debugp_param("nd_mid", ID2SYM(node->nd_mid));
Index: parse.y
===================================================================
--- parse.y	(revision 46364)
+++ parse.y	(revision 46365)
@@ -1206,7 +1206,7 @@ stmt		: keyword_alias fitem {lex_state = https://github.com/ruby/ruby/blob/trunk/parse.y#L1206
 			else if ($5 == tANDOP) {
 			    $5 = 1;
 			}
-			$$ = NEW_OP_ASGN1($1, $5, args);
+			$$ = NEW_OP_ASGN1(attr_receiver($1), $5, args);
 			fixpos($$, $1);
 		    /*%
 			$$ = dispatch2(aref_field, $1, escape_Qundef($3));
@@ -1998,7 +1998,7 @@ arg		: lhs '=' arg https://github.com/ruby/ruby/blob/trunk/parse.y#L1998
 			else if ($5 == tANDOP) {
 			    $5 = 1;
 			}
-			$$ = NEW_OP_ASGN1($1, $5, args);
+			$$ = NEW_OP_ASGN1(attr_receiver($1), $5, args);
 			fixpos($$, $1);
 		    /*%
 			$1 = dispatch2(aref_field, $1, escape_Qundef($3));
@@ -9650,6 +9650,7 @@ new_attr_op_assign_gen(struct parser_par https://github.com/ruby/ruby/blob/trunk/parse.y#L9650
     else if (op == tANDOP) {
 	op = 1;
     }
+    lhs = attr_receiver(lhs);
     asgn = NEW_OP_ASGN2(lhs, attr, op, rhs);
     fixpos(asgn, lhs);
     return asgn;
Index: test/ruby/test_assignment.rb
===================================================================
--- test/ruby/test_assignment.rb	(revision 46364)
+++ test/ruby/test_assignment.rb	(revision 46365)
@@ -102,8 +102,12 @@ class TestAssignment < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_assignment.rb#L102
   end
 
   def test_assign_private_self
+    bug9907 = '[ruby-core:62949] [Bug #9907]'
+
     o = Object.new
     class << o
+      def foo; 42; end
+      def [](i); 42; end
       private
       def foo=(a); 42; end
       def []=(i, a); 42; end
@@ -122,6 +126,20 @@ class TestAssignment < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_assignment.rb#L126
     assert_nothing_raised(NoMethodError) {
       assert_equal(1, o.instance_eval {self[0] = 1})
     }
+
+    assert_nothing_raised(NoMethodError, bug9907) {
+      assert_equal(43, o.instance_eval {self.foo += 1})
+    }
+    assert_nothing_raised(NoMethodError, bug9907) {
+      assert_equal(1, o.instance_eval {self.foo &&= 1})
+    }
+
+    assert_nothing_raised(NoMethodError, bug9907) {
+      assert_equal(43, o.instance_eval {self[0] += 1})
+    }
+    assert_nothing_raised(NoMethodError, bug9907) {
+      assert_equal(1, o.instance_eval {self[0] &&= 1})
+    }
   end
 
   def test_yield

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

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