[前][次][番号順一覧][スレッド一覧][生データ]

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

[前][次][番号順一覧][スレッド一覧][生データ]