From 7671828d45ea3b0d2f3814fc59bb01cba3d481d5 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Fri, 16 Jul 2010 12:24:28 +0800 Subject: [PATCH] Support nested for-each loops. Closes #79. --- src/boot/me/trans.ml | 54 ++++++++++++++++----------- src/test/run-pass/foreach-nested-2.rs | 38 +++++++++++++++++++ src/test/run-pass/foreach-nested.rs | 23 ++++++++++++ 3 files changed, 94 insertions(+), 21 deletions(-) create mode 100644 src/test/run-pass/foreach-nested-2.rs create mode 100644 src/test/run-pass/foreach-nested.rs diff --git a/src/boot/me/trans.ml b/src/boot/me/trans.ml index b4761ff2014..d690686c12b 100644 --- a/src/boot/me/trans.ml +++ b/src/boot/me/trans.ml @@ -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 index 00000000000..35487e7d92e --- /dev/null +++ b/src/test/run-pass/foreach-nested-2.rs @@ -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 index 00000000000..848adb26e70 --- /dev/null +++ b/src/test/run-pass/foreach-nested.rs @@ -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); +}