mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* compile.c (compile_massign), insns.def (expandarray): support
postarg with massign (a, *b, c = ...). * bootstraptest/test_massign.rb: add tests for above. * compile.h: fix debug macro names. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12631 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
99c58e9ebc
commit
30ab3f75f9
5 changed files with 259 additions and 88 deletions
|
@ -1,3 +1,12 @@
|
|||
Wed Jun 27 03:26:15 2007 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* compile.c (compile_massign), insns.def (expandarray): support
|
||||
postarg with massign (a, *b, c = ...).
|
||||
|
||||
* bootstraptest/test_massign.rb: add tests for above.
|
||||
|
||||
* compile.h: fix debug macro names.
|
||||
|
||||
Wed Jun 27 00:18:41 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* string.c (rb_str_clear): need to check STR_EMBED_P() before
|
||||
|
|
140
bootstraptest/test_massign.rb
Normal file
140
bootstraptest/test_massign.rb
Normal file
|
@ -0,0 +1,140 @@
|
|||
=begin
|
||||
# generated by this script:
|
||||
|
||||
3.times{|i|
|
||||
8.times{|e|
|
||||
ary = (0...e).to_a
|
||||
a,b,c,d,e,f = nil
|
||||
vals = %w(a b c d e f)
|
||||
vals[i] = '*' + vals[i]
|
||||
program = "#{vals.join(", ")} = *ary"
|
||||
eval(program)
|
||||
ans = [a,b,c,d,e,f]
|
||||
puts %Q{
|
||||
assert_equal "#{ans.inspect}", %q{
|
||||
ary = #{ary.inspect}
|
||||
#{program}; [a, b, c, d, e, f]
|
||||
}}
|
||||
}
|
||||
}
|
||||
=end
|
||||
|
||||
assert_equal "[[], nil, nil, nil, nil, nil]", %q{
|
||||
ary = []
|
||||
*a, b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[[], 0, nil, nil, nil, nil]", %q{
|
||||
ary = [0]
|
||||
*a, b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[[], 0, 1, nil, nil, nil]", %q{
|
||||
ary = [0, 1]
|
||||
*a, b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[[], 0, 1, 2, nil, nil]", %q{
|
||||
ary = [0, 1, 2]
|
||||
*a, b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[[], 0, 1, 2, 3, nil]", %q{
|
||||
ary = [0, 1, 2, 3]
|
||||
*a, b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[[], 0, 1, 2, 3, 4]", %q{
|
||||
ary = [0, 1, 2, 3, 4]
|
||||
*a, b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[[0], 1, 2, 3, 4, 5]", %q{
|
||||
ary = [0, 1, 2, 3, 4, 5]
|
||||
*a, b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[[0, 1], 2, 3, 4, 5, 6]", %q{
|
||||
ary = [0, 1, 2, 3, 4, 5, 6]
|
||||
*a, b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[nil, [], nil, nil, nil, nil]", %q{
|
||||
ary = []
|
||||
a, *b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[0, [], nil, nil, nil, nil]", %q{
|
||||
ary = [0]
|
||||
a, *b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[0, [], 1, nil, nil, nil]", %q{
|
||||
ary = [0, 1]
|
||||
a, *b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[0, [], 1, 2, nil, nil]", %q{
|
||||
ary = [0, 1, 2]
|
||||
a, *b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[0, [], 1, 2, 3, nil]", %q{
|
||||
ary = [0, 1, 2, 3]
|
||||
a, *b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[0, [], 1, 2, 3, 4]", %q{
|
||||
ary = [0, 1, 2, 3, 4]
|
||||
a, *b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[0, [1], 2, 3, 4, 5]", %q{
|
||||
ary = [0, 1, 2, 3, 4, 5]
|
||||
a, *b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[0, [1, 2], 3, 4, 5, 6]", %q{
|
||||
ary = [0, 1, 2, 3, 4, 5, 6]
|
||||
a, *b, c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[nil, nil, [], nil, nil, nil]", %q{
|
||||
ary = []
|
||||
a, b, *c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[0, nil, [], nil, nil, nil]", %q{
|
||||
ary = [0]
|
||||
a, b, *c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[0, 1, [], nil, nil, nil]", %q{
|
||||
ary = [0, 1]
|
||||
a, b, *c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[0, 1, [], 2, nil, nil]", %q{
|
||||
ary = [0, 1, 2]
|
||||
a, b, *c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[0, 1, [], 2, 3, nil]", %q{
|
||||
ary = [0, 1, 2, 3]
|
||||
a, b, *c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[0, 1, [], 2, 3, 4]", %q{
|
||||
ary = [0, 1, 2, 3, 4]
|
||||
a, b, *c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[0, 1, [2], 3, 4, 5]", %q{
|
||||
ary = [0, 1, 2, 3, 4, 5]
|
||||
a, b, *c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
||||
|
||||
assert_equal "[0, 1, [2, 3], 4, 5, 6]", %q{
|
||||
ary = [0, 1, 2, 3, 4, 5, 6]
|
||||
a, b, *c, d, e, f = *ary; [a, b, c, d, e, f]
|
||||
}
|
91
compile.c
91
compile.c
|
@ -1911,43 +1911,40 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *cond_seq, NODE *vals, LABEL *l1, VALUE s
|
|||
}
|
||||
|
||||
static int
|
||||
make_masgn_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node)
|
||||
make_masgn_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node)
|
||||
{
|
||||
|
||||
switch (nd_type(node)) {
|
||||
case NODE_ATTRASGN:{
|
||||
INSN *iobj;
|
||||
VALUE dupidx;
|
||||
case NODE_ATTRASGN: {
|
||||
INSN *iobj;
|
||||
VALUE dupidx;
|
||||
|
||||
COMPILE_POPED(ret, "masgn lhs (NODE_ATTRASGN)", node);
|
||||
POP_ELEMENT(ret); /* pop pop insn */
|
||||
iobj = (INSN *)POP_ELEMENT(ret); /* pop send insn */
|
||||
COMPILE_POPED(ret, "masgn lhs (NODE_ATTRASGN)", node);
|
||||
POP_ELEMENT(ret); /* pop pop insn */
|
||||
iobj = (INSN *)POP_ELEMENT(ret); /* pop send insn */
|
||||
|
||||
dupidx = iobj->operands[1];
|
||||
dupidx = INT2FIX(FIX2INT(dupidx) + 1);
|
||||
iobj->operands[1] = dupidx;
|
||||
dupidx = iobj->operands[1];
|
||||
dupidx = INT2FIX(FIX2INT(dupidx) + 1);
|
||||
iobj->operands[1] = dupidx;
|
||||
|
||||
ADD_INSN1(ret, nd_line(node), topn, dupidx);
|
||||
ADD_ELEM(ret, (LINK_ELEMENT *)iobj);
|
||||
ADD_INSN(ret, nd_line(node), pop); /* result */
|
||||
ADD_INSN(ret, nd_line(node), pop); /* rhs */
|
||||
break;
|
||||
ADD_INSN1(ret, nd_line(node), topn, dupidx);
|
||||
ADD_ELEM(ret, (LINK_ELEMENT *)iobj);
|
||||
ADD_INSN(ret, nd_line(node), pop); /* result */
|
||||
ADD_INSN(ret, nd_line(node), pop); /* rhs */
|
||||
break;
|
||||
}
|
||||
case NODE_MASGN: {
|
||||
COMPILE_POPED(ret, "nest masgn lhs", node);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
DECL_ANCHOR(anchor);
|
||||
COMPILE_POPED(anchor, "masgn lhs", node);
|
||||
/* dump_disasm_list(FIRST_ELEMENT(anchor)); */
|
||||
REMOVE_ELEM(FIRST_ELEMENT(anchor));
|
||||
/* dump_disasm_list(FIRST_ELEMENT(anchor)); */
|
||||
ADD_SEQ(ret, anchor);
|
||||
/* ADD_ELEM(ret, LAST_ELEMENT(anchor)); */
|
||||
}
|
||||
|
||||
case NODE_MASGN:
|
||||
COMPILE_POPED(ret, "nest masgn lhs", node);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
DECL_ANCHOR(anchor);
|
||||
COMPILE_POPED(anchor, "masgn lhs", node);
|
||||
/* dump_disasm_list(FIRST_ELEMENT(anchor)); */
|
||||
REMOVE_ELEM(FIRST_ELEMENT(anchor));
|
||||
/* dump_disasm_list(FIRST_ELEMENT(anchor)); */
|
||||
ADD_SEQ(ret, anchor);
|
||||
/* ADD_ELEM(ret, LAST_ELEMENT(anchor)); */
|
||||
}
|
||||
}
|
||||
|
||||
return COMPILE_OK;
|
||||
|
@ -1955,7 +1952,7 @@ make_masgn_lhs(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node)
|
|||
|
||||
static int
|
||||
compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret,
|
||||
NODE * rhsn, NODE * splatn, NODE * lhsn, int llen)
|
||||
NODE *rhsn, NODE *splatn, NODE *lhsn, int llen)
|
||||
{
|
||||
if (lhsn != 0) {
|
||||
compile_massign(iseq, ret, rhsn, splatn, lhsn->nd_next, llen + 1);
|
||||
|
@ -2040,7 +2037,27 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *ret,
|
|||
}
|
||||
|
||||
if (lhs_splat) {
|
||||
make_masgn_lhs(iseq, ret, splatn);
|
||||
if (nd_type(splatn) == NODE_POSTARG) {
|
||||
int i, num = splatn->nd_2nd->nd_alen;
|
||||
NODE *n = splatn->nd_2nd;
|
||||
|
||||
ADD_INSN (ret, nd_line(n), dup);
|
||||
ADD_INSN2(ret, nd_line(n), expandarray, INT2FIX(num), INT2FIX(2));
|
||||
|
||||
while (n) {
|
||||
DECL_ANCHOR(lhs);
|
||||
|
||||
COMPILE_POPED(lhs, "post", n->nd_head);
|
||||
REMOVE_ELEM(FIRST_ELEMENT(lhs));
|
||||
ADD_SEQ(ret, lhs);
|
||||
n = n->nd_next;
|
||||
}
|
||||
|
||||
make_masgn_lhs(iseq, ret, splatn->nd_1st);
|
||||
}
|
||||
else {
|
||||
make_masgn_lhs(iseq, ret, splatn);
|
||||
}
|
||||
}
|
||||
}
|
||||
return COMPILE_OK;
|
||||
|
@ -2507,8 +2524,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||
|
||||
if (node == 0) {
|
||||
if (!poped) {
|
||||
debug_nodeprint("NODE_NIL(implicit)");
|
||||
debug_nodeprint_close();
|
||||
debug_node_start("NODE_NIL(implicit)");
|
||||
debug_node_end();
|
||||
ADD_INSN(ret, 0, putnil);
|
||||
return COMPILE_OK;
|
||||
}
|
||||
|
@ -2516,7 +2533,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||
}
|
||||
|
||||
iseq->compile_data->last_line = nd_line(node);
|
||||
debug_nodeprint(node);
|
||||
debug_node_start(node);
|
||||
|
||||
type = nd_type(node);
|
||||
|
||||
|
@ -4378,7 +4395,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
debug_nodeprint_close();
|
||||
debug_node_end();
|
||||
return COMPILE_OK;
|
||||
}
|
||||
|
||||
|
|
10
compile.h
10
compile.h
|
@ -61,7 +61,7 @@
|
|||
|
||||
#define debug_node_start(node) \
|
||||
(ruby_debug_print_indent(-1, CPDEBUG, gl_node_level*2), \
|
||||
ruby_debug_print_node(10, CPDEBUG, header, node), gl_node_level++) \
|
||||
ruby_debug_print_node(10, CPDEBUG, "", (NODE *)node), gl_node_level++) \
|
||||
|
||||
#define debug_node_end() gl_node_level --;
|
||||
|
||||
|
@ -84,13 +84,13 @@ r_value(VALUE value)
|
|||
#define debugp_verbose(header, value) r_value(value)
|
||||
#define debugp_verbose_node(header, value) r_value(value)
|
||||
#define debugp_param(header, value) r_value(value)
|
||||
#define debug_nodeprint(node)
|
||||
#define debug_nodeprint_close()
|
||||
#define debug_node_start(node)
|
||||
#define debug_node_end()
|
||||
#endif
|
||||
|
||||
#if CPDEBUG > 1
|
||||
#define debugs ruby_debug_indent(-1, CPDEBUG, gl_node_level*2), printf
|
||||
#define debug_compile(msg, v) (ruby_debug_indent(-1, CPDEBUG, gl_node_level*2), printf("%s", msg), (v))
|
||||
#define debugs ruby_debug_print_indent(-1, CPDEBUG, gl_node_level*2), printf
|
||||
#define debug_compile(msg, v) (ruby_debug_print_indent(-1, CPDEBUG, gl_node_level*2), printf("%s", msg), (v))
|
||||
#else
|
||||
#define debugs if(0)printf
|
||||
#define debug_compile(msg, v) (v)
|
||||
|
|
97
insns.def
97
insns.def
|
@ -480,43 +480,67 @@ DEFINE_INSN
|
|||
expandarray
|
||||
(rb_num_t num, rb_num_t flag)
|
||||
(..., VALUE ary)
|
||||
(...) // inc += (num > 0) ? num - 1 + (flag ? 1 : 0) : num + 1 - (flag ? 1 : 0);
|
||||
(...) // inc += flag == 2 ? num : ((num > 0) ? num - 1 + (flag ? 1 : 0) : num + 1 - (flag ? 1 : 0));
|
||||
{
|
||||
int i;
|
||||
if ((long)num >= 0) {
|
||||
int len;
|
||||
if (TYPE(ary) != T_ARRAY) {
|
||||
ary = rb_ary_to_ary(ary);
|
||||
}
|
||||
len = RARRAY_LEN(ary);
|
||||
for (i = 0; i < len && i < num; i++) {
|
||||
PUSH(RARRAY_PTR(ary)[i]);
|
||||
}
|
||||
for (; i < num; i++) {
|
||||
PUSH(Qnil);
|
||||
}
|
||||
if (flag) {
|
||||
if (len > num) {
|
||||
PUSH(rb_ary_new4(len - num, &RARRAY_PTR(ary)[num]));
|
||||
|
||||
if (flag == 2) {
|
||||
VALUE *ptr = RARRAY_PTR(ary);
|
||||
int len = RARRAY_LEN(ary);
|
||||
int start = len - num;
|
||||
|
||||
if (start < 0) {
|
||||
for (i=0; i<num-len; i++) {
|
||||
PUSH(Qnil);
|
||||
}
|
||||
else {
|
||||
PUSH(rb_ary_new());
|
||||
for (i=0; i<len; i++) {
|
||||
PUSH(ptr[len-i-1]);
|
||||
}
|
||||
rb_ary_clear(ary);
|
||||
}
|
||||
else {
|
||||
for (i=0; i<num; i++) {
|
||||
PUSH(ptr[len-i-1]);
|
||||
}
|
||||
RARRAY_LEN(ary) = len - num;
|
||||
}
|
||||
}
|
||||
else {
|
||||
long holdnum = -num;
|
||||
VALUE val;
|
||||
|
||||
val = rb_ary_new4(holdnum, STACK_ADDR_FROM_TOP(holdnum));
|
||||
if (CLASS_OF(ary) == rb_cArray) {
|
||||
val = rb_ary_concat(val, ary);
|
||||
if ((long)num >= 0) {
|
||||
int len;
|
||||
if (TYPE(ary) != T_ARRAY) {
|
||||
ary = rb_ary_to_ary(ary);
|
||||
}
|
||||
len = RARRAY_LEN(ary);
|
||||
for (i = 0; i < len && i < num; i++) {
|
||||
PUSH(RARRAY_PTR(ary)[i]);
|
||||
}
|
||||
for (; i < num; i++) {
|
||||
PUSH(Qnil);
|
||||
}
|
||||
if (flag) {
|
||||
if (len > num) {
|
||||
PUSH(rb_ary_new4(len - num, &RARRAY_PTR(ary)[num]));
|
||||
}
|
||||
else {
|
||||
PUSH(rb_ary_new());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
rb_ary_push(val, ary);
|
||||
long holdnum = -num;
|
||||
VALUE val;
|
||||
|
||||
val = rb_ary_new4(holdnum, STACK_ADDR_FROM_TOP(holdnum));
|
||||
if (CLASS_OF(ary) == rb_cArray) {
|
||||
val = rb_ary_concat(val, ary);
|
||||
}
|
||||
else {
|
||||
rb_ary_push(val, ary);
|
||||
}
|
||||
POPN(holdnum);
|
||||
PUSH(val);
|
||||
}
|
||||
POPN(holdnum);
|
||||
PUSH(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -571,25 +595,6 @@ splatarray
|
|||
tmp = rb_ary_new3(1, ary);
|
||||
}
|
||||
obj = tmp;
|
||||
|
||||
if (0) {
|
||||
if (flag == Qfalse) {
|
||||
/* NODE_SPLAT */
|
||||
obj = rb_Array(ary);
|
||||
}
|
||||
else {
|
||||
/* NODE_SVALUE */
|
||||
if (RARRAY_LEN(ary) == 0) {
|
||||
obj = Qnil;
|
||||
}
|
||||
else if (RARRAY_LEN(ary) == 1) {
|
||||
obj = RARRAY_PTR(ary)[0];
|
||||
}
|
||||
else {
|
||||
obj = ary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue