summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-06-26 18:56:15 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-06-26 18:56:15 +0000
commit30ab3f75f9a8399c300359ea84e25f9a93df73ae (patch)
treeb3ec2146dec6a8344a47504d05f414b56cd98550
parent99c58e9ebcb90a81c2b6201d1d11ac1d5bd84604 (diff)
* 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
-rw-r--r--ChangeLog9
-rw-r--r--bootstraptest/test_massign.rb140
-rw-r--r--compile.c97
-rw-r--r--compile.h10
-rw-r--r--insns.def97
5 files changed, 262 insertions, 91 deletions
diff --git a/ChangeLog b/ChangeLog
index 9d6f4c671b..b1a94ef947 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/bootstraptest/test_massign.rb b/bootstraptest/test_massign.rb
new file mode 100644
index 0000000000..61272a3942
--- /dev/null
+++ b/bootstraptest/test_massign.rb
@@ -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]
+ }
diff --git a/compile.c b/compile.c
index ab2bbab857..43cda0c083 100644
--- a/compile.c
+++ b/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;
-
- 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;
-
- 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_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 */
+
+ 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;
+ }
+ 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;
}
diff --git a/compile.h b/compile.h
index 0e932c08a9..615c2d2268 100644
--- a/compile.h
+++ b/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)
diff --git a/insns.def b/insns.def
index 9db85ff162..8bd52fa496 100644
--- a/insns.def
+++ b/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;
- }
- }
- }
}
/**