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:
parent
7342e78ea6
commit
199f814f32
4 changed files with 42 additions and 15 deletions
|
@ -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
|
||||||
|
|
28
compile.c
28
compile.c
|
@ -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));
|
||||||
|
|
5
parse.y
5
parse.y
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue