summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlasdair Armstrong2018-03-02 14:24:00 +0000
committerAlasdair Armstrong2018-03-02 14:49:40 +0000
commitaad9ce3bda23efbab03595868bda7fc6dc3e03bf (patch)
tree5d0dcb30baf48aaaa934b5bed5d04c2a0d6bb55d
parent7cfbb697db209b96449a5c311b395d64d99e20a8 (diff)
Fix off-by-one error in OCaml for loop compilation
Fix for loop in interactive interpreter Fixes #8
-rw-r--r--src/interpreter.ml17
-rw-r--r--src/ocaml_backend.ml4
-rw-r--r--test/ocaml/for_bounds/expect4
-rw-r--r--test/ocaml/for_bounds/for_bounds.sail7
-rw-r--r--test/ocaml/for_bounds/test.isail4
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