1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46365 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2014-06-06 08:07:13 +00:00
parent 7342e78ea6
commit 199f814f32
4 changed files with 42 additions and 15 deletions

View file

@ -1,3 +1,9 @@
Fri Jun 6 17:07:08 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* 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@ruby-lang.org> Fri Jun 6 13:39:32 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* io.c (io_setstrbuf, io_read): should not shorten the given buffer until * io.c (io_setstrbuf, io_read): should not shorten the given buffer until

View file

@ -265,6 +265,11 @@ r_value(VALUE value)
(debug_compile("== " desc "\n", \ (debug_compile("== " desc "\n", \
iseq_compile_each(iseq, (anchor), (node), (poped)))) 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) \ #define OPERAND_AT(insn, idx) \
(((INSN*)(insn))->operands[(idx)]) (((INSN*)(insn))->operands[(idx)])
@ -3983,6 +3988,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
DECL_ANCHOR(args); DECL_ANCHOR(args);
VALUE argc; VALUE argc;
VALUE flag = 0; VALUE flag = 0;
VALUE asgnflag = 0;
ID id = node->nd_mid; ID id = node->nd_mid;
int boff = 0; int boff = 0;
@ -4012,7 +4018,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
if (!poped) { if (!poped) {
ADD_INSN(ret, line, putnil); 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)) { switch (nd_type(node->nd_args->nd_head)) {
case NODE_ZARRAY: case NODE_ZARRAY:
argc = INT2FIX(0); argc = INT2FIX(0);
@ -4026,6 +4032,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
} }
ADD_INSN1(ret, line, dupn, FIXNUM_INC(argc, 1 + boff)); ADD_INSN1(ret, line, dupn, FIXNUM_INC(argc, 1 + boff));
ADD_SEND_R(ret, line, ID2SYM(idAREF), argc, Qfalse, LONG2FIX(flag)); ADD_SEND_R(ret, line, ID2SYM(idAREF), argc, Qfalse, LONG2FIX(flag));
flag |= asgnflag;
if (id == 0 || id == 1) { if (id == 0 || id == 1) {
/* 0: or, 1: and /* 0: or, 1: and
@ -4121,6 +4128,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
} }
case NODE_OP_ASGN2:{ case NODE_OP_ASGN2:{
ID atype = node->nd_next->nd_mid; ID atype = node->nd_next->nd_mid;
VALUE asgnflag;
LABEL *lfin = NEW_LABEL(line); LABEL *lfin = NEW_LABEL(line);
LABEL *lcfin = NEW_LABEL(line); LABEL *lcfin = NEW_LABEL(line);
/* /*
@ -4165,7 +4173,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
*/ */
COMPILE(ret, "NODE_OP_ASGN2#recv", node->nd_recv); asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN2#recv", node);
ADD_INSN(ret, line, dup); ADD_INSN(ret, line, dup);
ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_vid), ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_vid),
INT2FIX(0)); INT2FIX(0));
@ -4182,8 +4190,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value); COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value);
ADD_INSN(ret, line, swap); ADD_INSN(ret, line, swap);
ADD_INSN1(ret, line, topn, INT2FIX(1)); ADD_INSN1(ret, line, topn, INT2FIX(1));
ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_aid), ADD_SEND_R(ret, line, ID2SYM(node->nd_next->nd_aid),
INT2FIX(1)); INT2FIX(1), Qfalse, INT2FIX(asgnflag));
ADD_INSNL(ret, line, jump, lfin); ADD_INSNL(ret, line, jump, lfin);
ADD_LABEL(ret, lcfin); ADD_LABEL(ret, lcfin);
@ -4204,8 +4212,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
ADD_INSN(ret, line, swap); ADD_INSN(ret, line, swap);
ADD_INSN1(ret, line, topn, INT2FIX(1)); ADD_INSN1(ret, line, topn, INT2FIX(1));
} }
ADD_SEND(ret, line, ID2SYM(node->nd_next->nd_aid), ADD_SEND_R(ret, line, ID2SYM(node->nd_next->nd_aid),
INT2FIX(1)); INT2FIX(1), Qfalse, INT2FIX(asgnflag));
ADD_INSN(ret, line, pop); ADD_INSN(ret, line, pop);
} }
break; break;
@ -5347,13 +5355,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
INIT_ANCHOR(args); INIT_ANCHOR(args);
argc = setup_args(iseq, args, node->nd_args, &flag); argc = setup_args(iseq, args, node->nd_args, &flag);
if (private_recv_p(node)) { flag |= COMPILE_RECV(recv, "recv", node);
flag |= VM_CALL_FCALL;
ADD_INSN(recv, line, putself);
}
else {
COMPILE(recv, "recv", node->nd_recv);
}
debugp_param("argc", argc); debugp_param("argc", argc);
debugp_param("nd_mid", ID2SYM(node->nd_mid)); debugp_param("nd_mid", ID2SYM(node->nd_mid));

View file

@ -1206,7 +1206,7 @@ stmt : keyword_alias fitem {lex_state = EXPR_FNAME;} fitem
else if ($5 == tANDOP) { else if ($5 == tANDOP) {
$5 = 1; $5 = 1;
} }
$$ = NEW_OP_ASGN1($1, $5, args); $$ = NEW_OP_ASGN1(attr_receiver($1), $5, args);
fixpos($$, $1); fixpos($$, $1);
/*% /*%
$$ = dispatch2(aref_field, $1, escape_Qundef($3)); $$ = dispatch2(aref_field, $1, escape_Qundef($3));
@ -1998,7 +1998,7 @@ arg : lhs '=' arg
else if ($5 == tANDOP) { else if ($5 == tANDOP) {
$5 = 1; $5 = 1;
} }
$$ = NEW_OP_ASGN1($1, $5, args); $$ = NEW_OP_ASGN1(attr_receiver($1), $5, args);
fixpos($$, $1); fixpos($$, $1);
/*% /*%
$1 = dispatch2(aref_field, $1, escape_Qundef($3)); $1 = dispatch2(aref_field, $1, escape_Qundef($3));
@ -9650,6 +9650,7 @@ new_attr_op_assign_gen(struct parser_params *parser, NODE *lhs, ID attr, ID op,
else if (op == tANDOP) { else if (op == tANDOP) {
op = 1; op = 1;
} }
lhs = attr_receiver(lhs);
asgn = NEW_OP_ASGN2(lhs, attr, op, rhs); asgn = NEW_OP_ASGN2(lhs, attr, op, rhs);
fixpos(asgn, lhs); fixpos(asgn, lhs);
return asgn; return asgn;

View file

@ -102,8 +102,12 @@ class TestAssignment < Test::Unit::TestCase
end end
def test_assign_private_self def test_assign_private_self
bug9907 = '[ruby-core:62949] [Bug #9907]'
o = Object.new o = Object.new
class << o class << o
def foo; 42; end
def [](i); 42; end
private private
def foo=(a); 42; end def foo=(a); 42; end
def []=(i, a); 42; end def []=(i, a); 42; end
@ -122,6 +126,20 @@ class TestAssignment < Test::Unit::TestCase
assert_nothing_raised(NoMethodError) { assert_nothing_raised(NoMethodError) {
assert_equal(1, o.instance_eval {self[0] = 1}) 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 end
def test_yield def test_yield