Skip to content

Commit 7671828

Browse files
jorendorffgraydon
authored andcommitted
Support nested for-each loops. Closes #79.
1 parent e1b8863 commit 7671828

File tree

3 files changed

+94
-21
lines changed

3 files changed

+94
-21
lines changed

src/boot/me/trans.ml

+33-21
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,11 @@ let trans_visitor
453453
Il.Mem (fp_imm out_mem_disp, args_rty)
454454
in
455455

456+
let fp_to_args (fp:Il.cell) (args_rty:Il.referent_ty): Il.cell =
457+
let (reg, _) = force_to_reg (Il.Cell fp) in
458+
Il.Mem(based_imm reg out_mem_disp, args_rty)
459+
in
460+
456461
let get_ty_param (ty_params:Il.cell) (param_idx:int) : Il.cell =
457462
get_element_ptr ty_params param_idx
458463
in
@@ -753,6 +758,28 @@ let trans_visitor
753758
Il.Mem (mem, (pointee_type ptr))
754759
in
755760

761+
(*
762+
* Within a for-each block, calculate the fp of an enclosing for-each block
763+
* or the enclosing function by chasing static links.
764+
*)
765+
let get_nth_outer_frame_ptr (diff:int) : Il.cell =
766+
(* All for-each block frames have the same args. *)
767+
let block_args_rty = current_fn_args_rty None in
768+
let current_fp = Il.Reg (abi.Abi.abi_fp_reg, Il.AddrTy Il.OpaqueTy) in
769+
let rec out (n:int) (fp:Il.cell) : Il.cell =
770+
if n == 0
771+
then fp
772+
else
773+
let args = fp_to_args fp block_args_rty in
774+
let iter_args = get_element_ptr args Abi.calltup_elt_iterator_args in
775+
let outer_fp =
776+
get_element_ptr iter_args Abi.iterator_args_elt_outer_frame_ptr
777+
in
778+
out (n - 1) outer_fp
779+
in
780+
out diff current_fp
781+
in
782+
756783
let cell_of_block_slot
757784
(slot_id:node_id)
758785
: Il.cell =
@@ -820,28 +847,13 @@ let trans_visitor
820847
in
821848
let diff = stmt_depth - slot_depth in
822849
let _ = annotate "get outer frame pointer" in
823-
let fp =
824-
get_iter_outer_frame_ptr_for_current_frame ()
850+
let fp = get_nth_outer_frame_ptr diff in
851+
let _ = annotate "calculate size" in
852+
let p =
853+
based_sz (get_ty_params_of_current_frame())
854+
(fst (force_to_reg (Il.Cell fp))) off
825855
in
826-
if diff > 1
827-
then
828-
bug () "unsupported nested for each loop";
829-
for i = 2 to diff do
830-
(* FIXME (issue #79): access outer
831-
* caller-block fps, given nearest
832-
* caller-block fp.
833-
*)
834-
let _ =
835-
annotate "step to outer-outer frame"
836-
in
837-
mov fp (Il.Cell fp)
838-
done;
839-
let _ = annotate "calculate size" in
840-
let p =
841-
based_sz (get_ty_params_of_current_frame())
842-
(fst (force_to_reg (Il.Cell fp))) off
843-
in
844-
Il.Mem (p, referent_type)
856+
Il.Mem (p, referent_type)
845857
else
846858
Il.Mem (fp_off_sz off, referent_type)
847859
end

src/test/run-pass/foreach-nested-2.rs

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// -*- rust -*-
2+
3+
iter two() -> int {
4+
put 0;
5+
put 1;
6+
}
7+
8+
iter range(int start, int stop) -> int {
9+
let int i = start;
10+
while (i < stop) {
11+
put i;
12+
i += 1;
13+
}
14+
}
15+
16+
fn main() {
17+
let vec[int] a = vec(-1, -1, -1, -1, -1, -1, -1, -1);
18+
let int p = 0;
19+
20+
for each (int i in two()) {
21+
for each (int j in range(0, 2)) {
22+
let int tmp = 10 * i + j;
23+
for each (int k in range(0, 2)) {
24+
a.(p) = 10 * tmp + k;
25+
p += 1;
26+
}
27+
}
28+
}
29+
30+
check (a.(0) == 0);
31+
check (a.(1) == 1);
32+
check (a.(2) == 10);
33+
check (a.(3) == 11);
34+
check (a.(4) == 100);
35+
check (a.(5) == 101);
36+
check (a.(6) == 110);
37+
check (a.(7) == 111);
38+
}

src/test/run-pass/foreach-nested.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// -*- rust -*-
2+
3+
iter two() -> int {
4+
put 0;
5+
put 1;
6+
}
7+
8+
fn main() {
9+
let vec[int] a = vec(-1, -1, -1, -1);
10+
let int p = 0;
11+
12+
for each (int i in two()) {
13+
for each (int j in two()) {
14+
a.(p) = 10 * i + j;
15+
p += 1;
16+
}
17+
}
18+
19+
check (a.(0) == 0);
20+
check (a.(1) == 1);
21+
check (a.(2) == 10);
22+
check (a.(3) == 11);
23+
}

0 commit comments

Comments
 (0)