Skip to content

Commit

Permalink
compile.c, parse.y: private op assign
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
nobu committed Jun 6, 2014
1 parent 7342e78 commit 199f814
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 15 deletions.
6 changes: 6 additions & 0 deletions ChangeLog
@@ -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
Expand Down
28 changes: 15 additions & 13 deletions compile.c
Expand Up @@ -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)])

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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);
/*
Expand Down Expand Up @@ -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));
Expand All @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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));
Expand Down
5 changes: 3 additions & 2 deletions parse.y
Expand Up @@ -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));
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
Expand Down
18 changes: 18 additions & 0 deletions test/ruby/test_assignment.rb
Expand Up @@ -102,8 +102,12 @@ def test_assign_abbreviated
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
Expand All @@ -122,6 +126,20 @@ def []=(i, a); 42; end
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
Expand Down

0 comments on commit 199f814

Please sign in to comment.