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>
* 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", \
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_ANCHOR *ret, NODE * node, int poped)
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_ANCHOR *ret, NODE * node, int poped)
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_ANCHOR *ret, NODE * node, int poped)
}
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_ANCHOR *ret, NODE * node, int poped)
}
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_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_SEND(ret, line, ID2SYM(node->nd_next->nd_vid),
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);
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_ANCHOR *ret, NODE * node, int poped)
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_ANCHOR *ret, NODE * node, int poped)
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));

View file

@ -1206,7 +1206,7 @@ stmt : keyword_alias fitem {lex_state = EXPR_FNAME;} fitem
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
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_params *parser, NODE *lhs, ID attr, ID op,
else if (op == tANDOP) {
op = 1;
}
lhs = attr_receiver(lhs);
asgn = NEW_OP_ASGN2(lhs, attr, op, rhs);
fixpos(asgn, lhs);
return asgn;

View file

@ -102,8 +102,12 @@ class TestAssignment < Test::Unit::TestCase
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::TestCase
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