yarv-diff:88
From: ko1 atdot.net
Date: 16 Aug 2005 10:52:40 -0000
Subject: [yarv-diff:88] r244 - in trunk: . yarvtest
Author: ko1
Date: 2005-08-16 19:52:40 +0900 (Tue, 16 Aug 2005)
New Revision: 244
Modified:
trunk/ChangeLog
trunk/compile.c
trunk/test1.rb
trunk/yarvtest/test_massign.rb
Log:
* compile.c : support nested massign
* yarvtest/test_massign.rb : add tests for above
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2005-08-16 01:26:27 UTC (rev 243)
+++ trunk/ChangeLog 2005-08-16 10:52:40 UTC (rev 244)
@@ -4,6 +4,13 @@
# from Mon, 03 May 2004 01:24:19 +0900
#
+2005-08-16(Tue) 19:51:19 +0900 Koichi Sasada <ko1 atdot.net>
+
+ * compile.c : support nested massign
+
+ * yarvtest/test_massign.rb : add tests for above
+
+
2005-08-16(Tue) 10:25:29 +0900 Koichi Sasada <ko1 atdot.net>
* eval.c : support rb_yield_0 with 0 args
Modified: trunk/compile.c
===================================================================
--- trunk/compile.c 2005-08-16 01:26:27 UTC (rev 243)
+++ trunk/compile.c 2005-08-16 10:52:40 UTC (rev 244)
@@ -1710,6 +1710,10 @@
break;
}
+ case NODE_MASGN:
+ COMPILE_POPED(ret, "nest masgn lhs", node);
+ break;
+
default:{
DECL_ANCHOR(anchor);
@@ -1721,6 +1725,112 @@
return COMPILE_OK;
}
+static int
+compile_massign(VALUE self, yarv_iseq_t *iseqobj, LINK_ANCHOR *ret,
+ NODE *rhsn, NODE *splatn, NODE *lhsn, int llen){
+ if(lhsn != 0){
+ compile_massign(self, iseqobj, ret, rhsn, splatn, lhsn->nd_next, llen + 1);
+ make_masgn_lhs(self, iseqobj, ret, lhsn->nd_head);
+ }
+ else{
+ int lhs_splat = 0;
+
+ if(splatn && (VALUE)splatn != -1){
+ lhs_splat = 1;
+ }
+
+ if(rhsn){
+ switch(nd_type(rhsn)){
+ case NODE_ARRAY:{
+ int rlen = rhsn->nd_alen;
+ int max = rlen > llen ? rlen : llen;
+ int i, si = 0;
+
+ for(i=0; i<max; i++){
+ if(i<rlen && i<llen){
+ /* a, b = c, d*/
+ COMPILE(ret, "masgn val1", rhsn->nd_head);
+ rhsn = rhsn->nd_next;
+ }
+ else if(i<rlen){
+ if(lhs_splat){
+ while(rhsn){
+ /* a, *b = x, y, z */
+ si++;
+ COMPILE(ret, "masgn rhs for lhs splat", rhsn->nd_head);
+ rhsn = rhsn->nd_next;
+ }
+ break;
+ }
+ else{
+ /* a, b = c, d, e */
+ COMPILE_POPED(ret, "masgn rhs (popped)", rhsn->nd_head);
+ rhsn = rhsn->nd_next;
+ }
+ }
+ else if(i<llen){
+ /* a, b, c = c, d */
+ ADD_INSN(ret, 0, putnil);
+ }
+ }
+
+ if(lhs_splat){
+ ADD_INSN1(ret, 0, newarray, I2F(si));
+ }
+ break;
+ }
+ case NODE_TO_ARY:
+ COMPILE (ret, "rhs to ary", rhsn->nd_head);
+ ADD_INSN2(ret, 0, expandarray, I2F(llen), lhs_splat);
+ break;
+
+ case NODE_SPLAT:
+ COMPILE (ret, "rhs to ary (splat)", rhsn->nd_head);
+ ADD_INSN2(ret, nd_line(rhsn), expandarray, I2F(llen), lhs_splat);
+ break;
+
+ case NODE_ARGSCAT:{
+ NODE *ary = rhsn->nd_head;
+ int idx = 0;
+ int rlen = rhsn->nd_head->nd_alen;
+
+ while(ary){
+ if(idx < llen || lhs_splat){
+ COMPILE(ret, "rhs aggscat each head", ary->nd_head);
+ }
+ else{
+ COMPILE_POPED(ret, "rhs aggscat each head (popped)", ary->nd_head);
+ }
+ ary = ary->nd_next;
+ idx++;
+ }
+
+ if(llen > idx){
+ COMPILE (ret, "rhs to ary (argscat/splat)", rhsn->nd_body);
+ ADD_INSN2(ret, nd_line(rhsn), expandarray, I2F(llen - idx), lhs_splat);
+ }
+ else if(lhs_splat){
+ COMPILE (ret, "rhs to ary (argscat/splat)", rhsn->nd_body);
+ ADD_INSN2(ret, nd_line(rhsn), expandarray, I2F(llen - idx), lhs_splat);
+ }
+ break;
+ }
+ default:
+ rb_bug("unknown rhs: %s", node_name(nd_type(rhsn)));
+ }
+ }
+ else{
+ /* nested massign */
+ ADD_INSN2(ret, 0, expandarray, INT2FIX(llen), lhs_splat);
+ }
+
+ if(lhs_splat){
+ make_masgn_lhs(self, iseqobj, ret, splatn);
+ }
+ }
+ return COMPILE_OK;
+}
+
static int defined_expr(VALUE self, yarv_iseq_t *iseqobj,
LINK_ANCHOR *ret, NODE *node, LABEL *lfinish, VALUE needstr){
char *estr = 0;
@@ -2447,111 +2557,13 @@
}
case NODE_MASGN:{
- NODE *rhsn = node->nd_value;
- NODE *lhsn = node->nd_head;
- int rlen, llen, i, max, si = 0;
- VALUE lhs_splat = Qfalse;
- DECL_ANCHOR(mlhs_seq);
-
- llen = 0;
- while(lhsn){
- make_masgn_lhs(self, iseqobj, mlhs_seq, lhsn->nd_head);
- llen += 1;
- lhsn = lhsn->nd_next;
- }
-
- if(node->nd_args && (long)node->nd_args != -1){
- make_masgn_lhs(self, iseqobj, mlhs_seq, node->nd_args);
- lhs_splat = Qtrue;
- }
-
- if(rhsn != 0){
- switch(nd_type(rhsn)){
- case NODE_ARRAY:
- rlen = rhsn->nd_alen;
- max = rlen > llen ? rlen : llen;
- debugs("l: %d, r: %d\n", llen, rlen);
-
- for(i=0; i<max; i++){
- if(i<rlen && i<llen){
- /* a, b = c, d*/
- COMPILE(ret, "masgn val1", rhsn->nd_head);
- rhsn = rhsn->nd_next;
- }
- else if(i<rlen){
- if(lhs_splat){
- while(rhsn){
- si++;
- COMPILE(ret, "masgn rhs for lhs splat", rhsn->nd_head);
- rhsn = rhsn->nd_next;
- }
- break;
- }
- else{
- /* a, b = c, d, e */
- COMPILE_POPED(ret, "masgn val2", rhsn->nd_head);
- rhsn = rhsn->nd_next;
- }
- }
- else if(i<llen){
- /* a, b, c = c, d */
- ADD_INSN(ret, nd_line(node), putnil);
- }
- }
-
- if(lhs_splat){
- ADD_INSN1(ret, nd_line(node), newarray, I2F(si));
- }
- break;
- case NODE_TO_ARY:
- COMPILE (ret, "rhs to ary", rhsn->nd_head);
- ADD_INSN2(ret, nd_line(node), expandarray, I2F(llen), lhs_splat);
- break;
-
- case NODE_SPLAT:
- COMPILE (ret, "rhs to ary (splat)", rhsn->nd_head);
- ADD_INSN2(ret, nd_line(node), expandarray, I2F(llen), lhs_splat);
- break;
-
- case NODE_ARGSCAT:{
- NODE *ary = rhsn->nd_head;
- int idx = 0;
-
- while(ary){
- if(idx < llen || lhs_splat){
- COMPILE(ret, "rhs aggscat each head", ary->nd_head);
- }
- else{
- COMPILE_POPED(ret, "rhs aggscat each head (popped)", ary->nd_head);
- }
- ary = ary->nd_next;
- idx++;
- }
- rlen = rhsn->nd_head->nd_alen;
- if(llen > idx){
- COMPILE (ret, "rhs to ary (argscat/splat)", rhsn->nd_body);
- ADD_INSN2(ret, nd_line(node), expandarray, I2F(llen - idx), lhs_splat);
- }
- else if(lhs_splat){
- COMPILE (ret, "rhs to ary (argscat/splat)", rhsn->nd_body);
- ADD_INSN2(ret, nd_line(node), expandarray, I2F(llen - idx), lhs_splat);
- }
- break;
- }
- default:
- rb_bug("unknown rhs: %s", node_name(nd_type(node->nd_value)));
- }
- }
- else{
- printf("??");
- }
- ADD_SEQ(ret, REVERSE_LIST(mlhs_seq));
-
+ compile_massign(self, iseqobj, ret, node->nd_value, node->nd_args, node->nd_head, 0);
if(!poped){
ADD_INSN(ret, nd_line(node), putnil);
}
break;
}
+
case NODE_LASGN:{
int idx = get_root_iseq_localsize(iseqobj) + 2 - node->nd_cnt;
Modified: trunk/test1.rb
===================================================================
--- trunk/test1.rb 2005-08-16 01:26:27 UTC (rev 243)
+++ trunk/test1.rb 2005-08-16 10:52:40 UTC (rev 244)
@@ -1,3 +1,31 @@
+#a = :a; b = :b; c = :c
+(a, *b), c, (d, e) = [1,2], 3, [4,5]
+p [a,b,c,d,e]
+__END__
+a, b, *c = :x, :y
+p [a, b, c]
+
+__END__
+(a, b), c, (d, e) = :x, :y, [:z1, :z2]
+
+p [a,b,c,d,e]
+
+__END__
+ary = [1,2,3]
+c = 4
+a, b, c = :x, :y, :z, *ary
+p [a, b, c]
+
+__END__
+a, *b = [1,2,3]
+p [a, b]
+
+__END__
+a = b = c = 1
+a, b, c = [1]
+p [a, b, c]
+
+__END__
a, (b, c) = [1, [2, 3]]
p [a, b, c]
Modified: trunk/yarvtest/test_massign.rb
===================================================================
--- trunk/yarvtest/test_massign.rb 2005-08-16 01:26:27 UTC (rev 243)
+++ trunk/yarvtest/test_massign.rb 2005-08-16 10:52:40 UTC (rev 244)
@@ -300,7 +300,45 @@
[a, b]
}
end
-
+
+ def test_nested_massign
+ ae %q{
+ (a, b), c = [[1, 2], 3]
+ [a, b, c]
+ }
+ ae %q{
+ a, (b, c) = [[1, 2], 3]
+ [a, b, c]
+ }
+ ae %q{
+ a, (b, c) = [1, [2, 3]]
+ [a, b, c]
+ }
+ ae %q{
+ (a, b), *c = [[1, 2], 3]
+ [a, b, c]
+ }
+ ae %q{
+ (a, b), c, (d, e) = [[1, 2], 3, [4, 5]]
+ [a, b, c, d, e]
+ }
+ ae %q{
+ (a, *b), c, (d, e, *) = [[1, 2], 3, [4, 5]]
+ [a, b, c, d, e]
+ }
+ ae %q{
+ (a, b), c, (d, *e) = [[1, 2, 3], 3, [4, 5, 6, 7]]
+ [a, b, c, d, e]
+ }
+ ae %q{
+ (a, (b1, b2)), c, (d, e) = [[1, 2], 3, [4, 5]]
+ [a, b1, b2, c, d, e]
+ }
+ ae %q{
+ (a, (b1, b2)), c, (d, e) = [[1, [21, 22]], 3, [4, 5]]
+ [a, b1, b2, c, d, e]
+ }
+ end
end
--
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml