1
0
Fork 0
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:
ko1 2007-06-26 18:56:15 +00:00
parent 99c58e9ebc
commit 30ab3f75f9
5 changed files with 259 additions and 88 deletions

View file

@ -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

View 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]
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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;
}
}
}
}
/**