]> git.lizzy.rs Git - rust.git/commitdiff
Support nested for-each loops. Closes #79.
authorJason Orendorff <jason.orendorff@gmail.com>
Fri, 16 Jul 2010 04:24:28 +0000 (12:24 +0800)
committerGraydon Hoare <graydon@pobox.com>
Fri, 16 Jul 2010 06:53:49 +0000 (14:53 +0800)
src/boot/me/trans.ml
src/test/run-pass/foreach-nested-2.rs [new file with mode: 0644]
src/test/run-pass/foreach-nested.rs [new file with mode: 0644]

index b4761ff2014afa5344979edf8a09cca46b20a6f4..d690686c12b7270bf18e26f471b182adf528b212 100644 (file)
@@ -453,6 +453,11 @@ let trans_visitor
     Il.Mem (fp_imm out_mem_disp, args_rty)
   in
 
+  let fp_to_args (fp:Il.cell) (args_rty:Il.referent_ty): Il.cell =
+    let (reg, _) = force_to_reg (Il.Cell fp) in
+    Il.Mem(based_imm reg out_mem_disp, args_rty)
+  in
+
   let get_ty_param (ty_params:Il.cell) (param_idx:int) : Il.cell =
       get_element_ptr ty_params param_idx
   in
@@ -753,6 +758,28 @@ let trans_visitor
             Il.Mem (mem, (pointee_type ptr))
   in
 
+  (*
+   * Within a for-each block, calculate the fp of an enclosing for-each block
+   * or the enclosing function by chasing static links.
+   *)
+  let get_nth_outer_frame_ptr (diff:int) : Il.cell =
+    (* All for-each block frames have the same args. *)
+    let block_args_rty = current_fn_args_rty None in
+    let current_fp = Il.Reg (abi.Abi.abi_fp_reg, Il.AddrTy Il.OpaqueTy) in
+    let rec out (n:int) (fp:Il.cell) : Il.cell =
+      if n == 0
+      then fp
+      else
+        let args = fp_to_args fp block_args_rty in
+        let iter_args = get_element_ptr args Abi.calltup_elt_iterator_args in
+        let outer_fp =
+          get_element_ptr iter_args Abi.iterator_args_elt_outer_frame_ptr
+        in
+          out (n - 1) outer_fp
+    in
+      out diff current_fp
+  in
+
   let cell_of_block_slot
       (slot_id:node_id)
       : Il.cell =
@@ -820,28 +847,13 @@ let trans_visitor
                             in
                             let diff = stmt_depth - slot_depth in
                             let _ = annotate "get outer frame pointer" in
-                            let fp =
-                              get_iter_outer_frame_ptr_for_current_frame ()
+                            let fp = get_nth_outer_frame_ptr diff in
+                            let _ = annotate "calculate size" in
+                            let p =
+                              based_sz (get_ty_params_of_current_frame())
+                                (fst (force_to_reg (Il.Cell fp))) off
                             in
-                              if diff > 1
-                              then
-                                bug () "unsupported nested for each loop";
-                              for i = 2 to diff do
-                                (* FIXME (issue #79): access outer
-                                 * caller-block fps, given nearest
-                                 * caller-block fp. 
-                                 *)
-                                let _ =
-                                  annotate "step to outer-outer frame"
-                                in
-                                  mov fp (Il.Cell fp)
-                              done;
-                              let _ = annotate "calculate size" in
-                              let p =
-                                based_sz (get_ty_params_of_current_frame())
-                                  (fst (force_to_reg (Il.Cell fp))) off
-                              in
-                                Il.Mem (p, referent_type)
+                              Il.Mem (p, referent_type)
                           else
                             Il.Mem (fp_off_sz off, referent_type)
             end
diff --git a/src/test/run-pass/foreach-nested-2.rs b/src/test/run-pass/foreach-nested-2.rs
new file mode 100644 (file)
index 0000000..35487e7
--- /dev/null
@@ -0,0 +1,38 @@
+// -*- rust -*-
+
+iter two() -> int {
+    put 0;
+    put 1;
+}
+
+iter range(int start, int stop) -> int {
+    let int i = start;
+    while (i < stop) {
+        put i;
+        i += 1;
+    }
+}
+
+fn main() {
+    let vec[int] a = vec(-1, -1, -1, -1, -1, -1, -1, -1);
+    let int p = 0;
+
+    for each (int i in two()) {
+        for each (int j in range(0, 2)) {
+            let int tmp = 10 * i + j;
+            for each (int k in range(0, 2)) {
+                a.(p) = 10 * tmp + k;
+                p += 1;
+            }
+        }
+    }
+
+    check (a.(0) == 0);
+    check (a.(1) == 1);
+    check (a.(2) == 10);
+    check (a.(3) == 11);
+    check (a.(4) == 100);
+    check (a.(5) == 101);
+    check (a.(6) == 110);
+    check (a.(7) == 111);
+}
diff --git a/src/test/run-pass/foreach-nested.rs b/src/test/run-pass/foreach-nested.rs
new file mode 100644 (file)
index 0000000..848adb2
--- /dev/null
@@ -0,0 +1,23 @@
+// -*- rust -*-
+
+iter two() -> int {
+    put 0;
+    put 1;
+}
+
+fn main() {
+    let vec[int] a = vec(-1, -1, -1, -1);
+    let int p = 0;
+
+    for each (int i in two()) {
+        for each (int j in two()) {
+            a.(p) = 10 * i + j;
+            p += 1;
+        }
+    }
+
+    check (a.(0) == 0);
+    check (a.(1) == 1);
+    check (a.(2) == 10);
+    check (a.(3) == 11);
+}