diff options
| author | Alasdair Armstrong | 2018-03-02 14:24:00 +0000 |
|---|---|---|
| committer | Alasdair Armstrong | 2018-03-02 14:49:40 +0000 |
| commit | aad9ce3bda23efbab03595868bda7fc6dc3e03bf (patch) | |
| tree | 5d0dcb30baf48aaaa934b5bed5d04c2a0d6bb55d | |
| parent | 7cfbb697db209b96449a5c311b395d64d99e20a8 (diff) | |
Fix off-by-one error in OCaml for loop compilation
Fix for loop in interactive interpreter
Fixes #8
| -rw-r--r-- | src/interpreter.ml | 17 | ||||
| -rw-r--r-- | src/ocaml_backend.ml | 4 | ||||
| -rw-r--r-- | test/ocaml/for_bounds/expect | 4 | ||||
| -rw-r--r-- | test/ocaml/for_bounds/for_bounds.sail | 7 | ||||
| -rw-r--r-- | test/ocaml/for_bounds/test.isail | 4 |
5 files changed, 34 insertions, 2 deletions
diff --git a/src/interpreter.ml b/src/interpreter.ml index e39c90f0..55dcbed0 100644 --- a/src/interpreter.ml +++ b/src/interpreter.ml @@ -516,6 +516,23 @@ let rec step (E_aux (e_aux, annot) as orig_exp) = | Right exp' -> wrap (E_try (exp', pexps)) end + | E_for (id, exp_from, exp_to, exp_step, ord, body) when is_value exp_from && is_value exp_to && is_value exp_step -> + let v_from = value_of_exp exp_from in + let v_to = value_of_exp exp_to in + let v_step = value_of_exp exp_step in + begin match value_gt [v_from; v_to] with + | V_bool true -> wrap (E_lit (L_aux (L_unit, Parse_ast.Unknown))) + | V_bool false -> + wrap (E_block [subst id v_from body; E_aux (E_for (id, exp_of_value (value_add_int [v_from; v_step]), exp_to, exp_step, ord, body), annot)]) + | _ -> assert false + end + | E_for (id, exp_from, exp_to, exp_step, ord, body) when is_value exp_to && is_value exp_step -> + step exp_from >>= fun exp_from' -> wrap (E_for (id, exp_from', exp_to, exp_step, ord, body)) + | E_for (id, exp_from, exp_to, exp_step, ord, body) when is_value exp_step -> + step exp_to >>= fun exp_to' -> wrap (E_for (id, exp_from, exp_to', exp_step, ord, body)) + | E_for (id, exp_from, exp_to, exp_step, ord, body) -> + step exp_step >>= fun exp_step' -> wrap (E_for (id, exp_from, exp_to, exp_step', ord, body)) + | E_sizeof _ | E_constraint _ -> assert false (* Must be re-written before interpreting *) | _ -> failwith ("Unimplemented " ^ string_of_exp orig_exp) diff --git a/src/ocaml_backend.ml b/src/ocaml_backend.ml index 22bb7de6..795b6300 100644 --- a/src/ocaml_backend.ml +++ b/src/ocaml_backend.ml @@ -273,8 +273,8 @@ let rec ocaml_exp ctx (E_aux (exp_aux, _) as exp) = in let loop_compare = match ord with - | Ord_aux (Ord_inc, _) -> string "Big_int.less" - | Ord_aux (Ord_dec, _) -> string "Big_int.greater" + | Ord_aux (Ord_inc, _) -> string "Big_int.less_equal" + | Ord_aux (Ord_dec, _) -> string "Big_int.greater_equal" | Ord_aux (Ord_var _, _) -> failwith "Cannot have variable loop order!" in let loop_body = diff --git a/test/ocaml/for_bounds/expect b/test/ocaml/for_bounds/expect new file mode 100644 index 00000000..6c06f0e0 --- /dev/null +++ b/test/ocaml/for_bounds/expect @@ -0,0 +1,4 @@ +i=0 +i=1 +i=2 +i=3 diff --git a/test/ocaml/for_bounds/for_bounds.sail b/test/ocaml/for_bounds/for_bounds.sail new file mode 100644 index 00000000..a7388a85 --- /dev/null +++ b/test/ocaml/for_bounds/for_bounds.sail @@ -0,0 +1,7 @@ + +val main : unit -> unit +function main () = { + foreach(i from 0 to 3) { + print_int("i=", i); + } +} diff --git a/test/ocaml/for_bounds/test.isail b/test/ocaml/for_bounds/test.isail new file mode 100644 index 00000000..6a9595e3 --- /dev/null +++ b/test/ocaml/for_bounds/test.isail @@ -0,0 +1,4 @@ +:output result +main() +:run +:quit
\ No newline at end of file |
