summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlasdair Armstrong2017-09-01 14:27:34 +0100
committerAlasdair Armstrong2017-09-01 14:27:34 +0100
commit4878a4706e276b8d1aa8a6808e88faeba7789049 (patch)
tree793108c995866adb79082d6d0d36d241d3bd60f2
parent7e143cc0d5040ebfa9983be58ab66a83eee04573 (diff)
Started work on test suite for ocaml backend
-rw-r--r--src/ocaml_backend.ml72
-rw-r--r--test/ocaml/hello_world/expect2
-rw-r--r--test/ocaml/hello_world/hello_world.sail19
-rw-r--r--test/ocaml/prelude.sail138
-rwxr-xr-xtest/ocaml/run_tests.sh69
-rw-r--r--test/ocaml/sail_lib.ml169
-rw-r--r--test/ocaml/string_equality/expect1
-rw-r--r--test/ocaml/string_equality/string_equality.sail10
-rwxr-xr-xtest/typecheck/run_tests.sh32
9 files changed, 477 insertions, 35 deletions
diff --git a/src/ocaml_backend.ml b/src/ocaml_backend.ml
index 8c8b8103..8b88a07e 100644
--- a/src/ocaml_backend.ml
+++ b/src/ocaml_backend.ml
@@ -30,18 +30,31 @@ let zchar c =
let zencode_string str = "z" ^ List.fold_left (fun s1 s2 -> s1 ^ s2) "" (List.map zchar (Util.string_to_list str))
+let zencode_upper_string str = "Z" ^ List.fold_left (fun s1 s2 -> s1 ^ s2) "" (List.map zchar (Util.string_to_list str))
+
let zencode ctx id =
try string (string_of_id (Bindings.find id ctx.externs)) with
| Not_found -> string (zencode_string (string_of_id id))
+let zencode_upper ctx id =
+ try string (string_of_id (Bindings.find id ctx.externs)) with
+ | Not_found -> string (zencode_upper_string (string_of_id id))
+
let zencode_kid kid = string ("'" ^ zencode_string (string_of_id (id_of_kid kid)))
+let ocaml_typ_id ctx = function
+ | id when Id.compare id (mk_id "string") = 0 -> string "string"
+ | id when Id.compare id (mk_id "list") = 0 -> string "list"
+ | id when Id.compare id (mk_id "bit") = 0 -> string "bit"
+ | id when Id.compare id (mk_id "int") = 0 -> string "big_int"
+ | id when Id.compare id (mk_id "bool") = 0 -> string "bool"
+ | id -> zencode ctx id
+
let rec ocaml_typ ctx (Typ_aux (typ_aux, _)) =
match typ_aux with
- | Typ_id id when Id.compare id (mk_id "string") = 0 -> string "string"
- | Typ_id id -> zencode ctx id
- | Typ_app (id, []) -> zencode ctx id
- | Typ_app (id, typs) -> parens (separate_map (string " * ") (ocaml_typ_arg ctx) typs) ^^ space ^^ zencode ctx id
+ | Typ_id id -> ocaml_typ_id ctx id
+ | Typ_app (id, []) -> ocaml_typ_id ctx id
+ | Typ_app (id, typs) -> parens (separate_map (string " * ") (ocaml_typ_arg ctx) typs) ^^ space ^^ ocaml_typ_id ctx id
| Typ_tup typs -> parens (separate_map (string " * ") (ocaml_typ ctx) typs)
| Typ_fn (typ1, typ2, _) -> separate space [ocaml_typ ctx typ1; string "->"; ocaml_typ ctx typ2]
| Typ_var kid -> zencode_kid kid
@@ -68,7 +81,7 @@ let ocaml_lit (L_aux (lit_aux, _)) =
| L_one -> string "B1"
| L_true -> string "true"
| L_false -> string "false"
- | L_num n -> string (string_of_int n)
+ | L_num n -> parens (string "big_int_of_int" ^^ space ^^ string (string_of_int n))
| L_undef -> failwith "undefined should have been re-written prior to ocaml backend"
| L_string str -> dquotes (string (String.escaped str))
| _ -> string "LIT"
@@ -115,8 +128,8 @@ let rec ocaml_exp ctx (E_aux (exp_aux, _) as exp) =
separate space [string "let"; ocaml_letbind ctx lb; string "in"]
^/^ ocaml_exp ctx exp
| E_internal_let (lexp, exp1, exp2) ->
- separate space [string "let"; string "ref"; ocaml_atomic_lexp ctx lexp;
- equals; ocaml_exp ctx exp1; string "in"]
+ separate space [string "let"; ocaml_atomic_lexp ctx lexp;
+ equals; string "ref"; ocaml_atomic_exp ctx exp1; string "in"]
^/^ ocaml_exp ctx exp2
| E_lit _ | E_list _ | E_id _ | E_tuple _ -> ocaml_atomic_exp ctx exp
| _ -> string ("EXP(" ^ string_of_exp exp ^ ")")
@@ -147,7 +160,8 @@ and ocaml_atomic_exp ctx (E_aux (exp_aux, _) as exp) =
| E_id id ->
begin
match Env.lookup_id id (env_of exp) with
- | Local (Immutable, _) | Unbound | Enum _ -> zencode ctx id
+ | Local (Immutable, _) | Unbound -> zencode ctx id
+ | Enum _ -> zencode_upper ctx id
| Register _ | Local (Mutable, _) -> bang ^^ zencode ctx id
| _ -> failwith ("Union constructor: " ^ zencode_string (string_of_id id))
end
@@ -173,7 +187,7 @@ let rec get_initialize_registers = function
let initial_value_for id inits =
let find_reg = function
- | E_aux (E_assign (LEXP_aux (LEXP_cast (_, reg_id), _), init), _) -> Some init
+ | E_aux (E_assign (LEXP_aux (LEXP_cast (_, reg_id), _), init), _) when Id.compare id reg_id = 0 -> Some init
| _ -> None
in
match Util.option_first find_reg inits with
@@ -188,13 +202,29 @@ let ocaml_dec_spec ctx (DEC_aux (reg, _)) =
string "ref"; parens (ocaml_exp ctx (initial_value_for id ctx.register_inits))]
| _ -> failwith "Unsupported register declaration"
+let funcls_id = function
+ | [] -> failwith "Ocaml: empty function"
+ | FCL_aux (FCL_Funcl (id, pat, exp),_) :: _ -> id
+
+let ocaml_funcl_match ctx (FCL_aux (FCL_Funcl (id, pat, exp), _)) =
+ separate space [bar; ocaml_pat ctx pat; string "->"]
+ ^//^ group (string "with_return (fun r ->" ^//^ ocaml_exp ctx exp ^^ rparen)
+
+let rec ocaml_funcl_matches ctx = function
+ | [] -> failwith "Ocaml: empty function"
+ | [clause] -> ocaml_funcl_match ctx clause
+ | (clause :: clauses) -> ocaml_funcl_match ctx clause ^/^ ocaml_funcl_matches ctx clauses
+
let ocaml_funcls ctx = function
| [] -> failwith "Ocaml: empty function"
| [FCL_aux (FCL_Funcl (id, pat, exp),_)] ->
separate space [string "let"; zencode ctx id; ocaml_pat ctx pat; equals; string "with_return (fun r ->"]
^//^ ocaml_exp ctx exp
^^ rparen
- | _ -> string "MBF" (* failwith "Ocaml: multi-body function should have been re-written by now" *)
+ | funcls ->
+ let id = funcls_id funcls in
+ separate space [string "let"; zencode ctx id; equals; string "function"]
+ ^//^ ocaml_funcl_matches ctx funcls
let ocaml_fundef ctx (FD_aux (FD_function (_, _, _, funcls), _)) =
ocaml_funcls ctx funcls
@@ -219,8 +249,8 @@ let rec ocaml_cases ctx =
| [] -> empty
let rec ocaml_enum ctx = function
- | [id] -> zencode ctx id
- | id :: ids -> zencode ctx id ^/^ ocaml_enum ctx ids
+ | [id] -> zencode_upper ctx id
+ | id :: ids -> zencode_upper ctx id ^/^ (bar ^^ space ^^ ocaml_enum ctx ids)
| [] -> empty
let ocaml_typedef ctx (TD_aux (td_aux, _)) =
@@ -234,7 +264,7 @@ let ocaml_typedef ctx (TD_aux (td_aux, _)) =
^//^ ocaml_cases ctx cases
| TD_enum (id, _, ids, _) ->
separate space [string "type"; zencode ctx id; equals]
- ^//^ ocaml_enum ctx ids
+ ^//^ (bar ^^ space ^^ ocaml_enum ctx ids)
| TD_abbrev (id, _, TypSchm_aux (TypSchm_ts (typq, typ), _)) ->
separate space [string "type"; ocaml_typquant typq; zencode ctx id; equals; ocaml_typ ctx typ]
| _ -> failwith "Unsupported typedef"
@@ -270,19 +300,21 @@ let ocaml_defs (Defs defs) =
let empty_reg_init =
if ctx.register_inits = []
then
- separate space [string "let"; zencode ctx (mk_id "initialize_registers"); string "()"; equals; string "()"]
+ separate space [string "let"; string "initialize_registers"; string "()"; equals; string "()"]
^^ ocaml_def_end
else empty
in
- (string "open Sail_lib" ^^ ocaml_def_end)
+ (string "open Sail_lib;;" ^^ hardline)
+ ^^ (string "open Big_int" ^^ ocaml_def_end)
^^ concat (List.map (ocaml_def ctx) defs)
^^ empty_reg_init
let ocaml_main spec =
concat [separate space [string "open"; string (String.capitalize spec)] ^^ ocaml_def_end;
separate space [string "let"; string "()"; equals]
- ^//^ (string "initialize_registers" ^^ string "()" ^^ semi
- ^/^ string "zmain" ^^ string "()")
+ ^//^ (string "Random.self_init ();"
+ ^/^ string "initialize_registers ();"
+ ^/^ string "zmain ()")
]
let ocaml_pp_defs f defs =
@@ -305,9 +337,11 @@ let ocaml_compile spec defs =
let out_chan = open_out "main.ml" in
ToChannel.pretty 1. 80 out_chan (ocaml_main spec);
close_out out_chan;
- let _ = Unix.system "ocamlbuild main.native" in
+ let _ = Unix.system "ocamlbuild -lib nums main.native" in
let _ = Unix.system ("cp main.native " ^ cwd ^ "/" ^ spec) in
()
- else ();
+ else
+ let _ = Unix.system ("ocamlbuild -lib nums " ^ spec ^ ".cmo") in
+ ();
Unix.chdir cwd
diff --git a/test/ocaml/hello_world/expect b/test/ocaml/hello_world/expect
new file mode 100644
index 00000000..3df47a31
--- /dev/null
+++ b/test/ocaml/hello_world/expect
@@ -0,0 +1,2 @@
+Hello, Sail!
+Hello, World!
diff --git a/test/ocaml/hello_world/hello_world.sail b/test/ocaml/hello_world/hello_world.sail
new file mode 100644
index 00000000..d96429f2
--- /dev/null
+++ b/test/ocaml/hello_world/hello_world.sail
@@ -0,0 +1,19 @@
+
+val unit -> string effect pure hello_world
+
+function hello_world () = {
+ return "Hello, World!";
+ "Unreachable"
+}
+
+val unit -> unit effect {wreg, rreg} main
+
+register string REG
+
+function main () = {
+ REG := "Hello, Sail!";
+ print(REG);
+ REG := hello_world ();
+ print(REG);
+ return ()
+}
diff --git a/test/ocaml/prelude.sail b/test/ocaml/prelude.sail
new file mode 100644
index 00000000..2526d109
--- /dev/null
+++ b/test/ocaml/prelude.sail
@@ -0,0 +1,138 @@
+
+default Order dec
+
+val extern (int, int) -> bool effect pure eq_int = "eq_int"
+val extern forall 'n. (bit['n], bit['n]) -> bool effect pure eq_vec = "eq_list"
+val extern (string, string) -> bool effect pure eq_string = "eq_string"
+val (real, real) -> bool effect pure eq_real
+
+val extern forall Type 'a. ('a, 'a) -> bool effect pure eq_anything = "(fun (x, y) -> x == y)"
+
+overload (deinfix ==) [eq_int; eq_vec; eq_string; eq_real; eq_anything]
+
+val extern forall Type 'a, Num 'n. vector<'n - 1, 'n, dec, 'a> -> [:'n:] effect pure length = "length"
+
+val extern forall Num 'n, Num 'm, Num 'o (* , 'm >= 'o, 'o >= 0, 'n >= 'm + 1 *).
+ (bit['n], [:'m:], [:'o:]) -> bit['m - ('o - 1)] effect pure vector_subrange = "subrange"
+
+val extern forall Num 'n, Type 'a. (vector<'n - 1, 'n, dec, 'a>, int) -> 'a effect pure vector_access = "access"
+
+val extern forall Num 'n, Type 'a. (vector<'n - 1, 'n, dec, 'a>, int, 'a) -> vector<'n - 1, 'n, dec, 'a> effect pure vector_update = "update"
+
+val extern forall Num 'n, Num 'm, Num 'o.
+ (bit['n], [:'m:], [:'o:], bit['m - ('o - 1)]) -> bit['n]
+ effect pure vector_update_subrange = "update_subrange"
+
+val forall Num 'n, Type 'a. ('a, vector<'n - 1, 'n, dec, 'a>) -> vector<'n, 'n + 1, dec, 'a> effect pure vcons
+
+val extern forall Num 'n, Num 'm, Type 'a. (vector<'n - 1, 'n, dec, 'a>, vector<'m - 1, 'm, dec, 'a>) -> vector<('n + 'm) - 1, 'n + 'm, dec, 'a> effect pure append = "append"
+
+val extern bool -> bool effect pure not_bool = "not"
+val extern forall 'n. bit['n] -> bit['n] effect pure not_vec = "not_vec"
+
+overload ~ [not_bool; not_vec]
+
+val forall Type 'a. ('a, 'a) -> bool effect pure neq_anything
+
+function neq_anything (x, y) = not_bool (x == y)
+
+overload (deinfix !=) [neq_anything]
+
+val extern (bool, bool) -> bool effect pure and_bool = "and_bool"
+val extern forall 'n. (bit['n], bit['n]) -> bit['n] effect pure and_vec = "and_vec"
+
+overload (deinfix &) [and_bool; and_vec]
+
+val extern (bool, bool) -> bool effect pure or_bool = "or_bool"
+val extern forall 'n. (bit['n], bit['n]) -> bit['n] effect pure or_vec = "or_vec"
+
+overload (deinfix |) [or_bool; or_vec]
+
+val extern forall 'n. bit['n] -> [|0:2**'n - 1|] effect pure UInt = "uint"
+
+val extern forall 'n. bit['n] -> [|- 2**('n - 1):2**('n - 1) - 1|] effect pure SInt = "sint"
+
+val extern string -> unit effect pure print = "print_endline"
+val extern (string, string) -> string effect pure concat_str = "concat_string"
+val int -> string effect pure DecStr
+val int -> string effect pure HexStr
+
+val forall 'n. (bit['n], bit['n]) -> bit['n] effect pure xor_vec
+val (int, int) -> int effect pure int_exp
+
+overload (deinfix ^) [xor_vec; int_exp]
+
+val extern forall 'n, 'm, 'o, 'p. ([|'n:'m|], [|'o:'p|]) -> [|'n+'o:'m+'p|] effect pure add_range = "add"
+val extern (int, int) -> int effect pure add_int = "add"
+val extern forall 'n. (bit['n], bit['n]) -> bit['n] effect pure add_vec = "add_vec"
+val forall 'n. (bit['n], int) -> bit['n] effect pure add_vec_int
+
+overload (deinfix +) [add_range; add_int; add_vec; add_vec_int]
+
+val extern forall 'n, 'm, 'o, 'p. ([|'n:'m|], [|'o:'p|]) -> [|'n-'p:'m-'o|] effect pure sub_range = "sub"
+val extern (int, int) -> int effect pure sub_int = "sub"
+val forall 'n. (bit['n], bit['n]) -> bit['n] effect pure sub_vec
+val forall 'n. (bit['n], int) -> bit ['n] effect pure sub_vec_int
+
+val forall 'n. [|'n:'m|] -> [|-'m:-'n|] effect pure negate_range
+val int -> int effect pure negate_int
+
+overload (deinfix -) [sub_range; sub_int; sub_vec; sub_vec_int]
+overload negate [negate_range; negate_int]
+
+val extern forall 'n, 'm, 'o, 'p. ([|'n:'m|], [|'o:'p|]) -> [|'n * 'o : 'm * 'p|] effect pure mult_range = "mult"
+val extern (int, int) -> int effect pure mult_int = "mult"
+
+overload (deinfix * ) [mult_range; mult_int]
+
+val (int, int) -> bool effect pure gteq_int
+val (real, real) -> bool effect pure gteq_real
+
+overload (deinfix >=) [gteq_int; gteq_real]
+
+val (int, int) -> bool effect pure lteq_int
+val (real, real) -> bool effect pure lteq_real
+
+overload (deinfix <=) [lteq_int; lteq_real]
+
+val (int, int) -> bool effect pure gt_int
+val (real, real) -> bool effect pure gt_real
+
+overload (deinfix >) [gt_int; gt_real]
+
+val (int, int) -> bool effect pure lt_int
+val (real, real) -> bool effect pure lt_real
+
+overload (deinfix <) [lt_int; lt_real]
+
+val real -> int effect pure RoundDown
+val real -> int effect pure RoundUp
+
+val extern (int, int) -> int effect pure quotient = "quotient"
+
+overload (deinfix quot) [quotient]
+
+val extern (int, int) -> int effect pure modulus = "modulus"
+
+overload (deinfix mod) [modulus]
+
+val extern (int, int) -> int effect pure shl_int
+val extern (int, int) -> int effect pure shr_int
+
+val (nat, nat) -> nat effect pure min_nat
+val (int, int) -> int effect pure min_int
+val (nat, nat) -> nat effect pure max_nat
+val (int, int) -> int effect pure max_int
+
+overload min [min_nat; min_int]
+overload max [max_nat; max_int]
+
+val extern forall 'n, 'm. ([:'m:], [:'n:], bit['m], bit['m], bit[8 * 'n]) -> unit effect {wmem} __WriteRAM = "write_ram"
+val extern forall 'n, 'm. ([:'m:], [:'n:], bit['m], bit['m]) -> bit[8 * 'n] effect {rmem} __ReadRAM = "read_ram"
+
+val extern forall 'n, 'm. (bit['n], [:'m:]) -> bit['n * 'm] effect pure replicate_bits
+
+val extern nat -> exist 'n, 'n >= 0. [:'n:] effect pure ex_nat = "identity"
+val extern int -> exist 'n. [:'n:] effect pure ex_int = "identity"
+val extern forall 'n, 'm. [|'n:'m|] -> exist 'o, 'n <= 'o & 'o <= 'm. [:'o:] effect pure ex_range = "identity"
+
diff --git a/test/ocaml/run_tests.sh b/test/ocaml/run_tests.sh
new file mode 100755
index 00000000..d01535b6
--- /dev/null
+++ b/test/ocaml/run_tests.sh
@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+set -e
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+SAILDIR="$DIR/../.."
+
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[0;33m'
+NC='\033[0m'
+
+rm -f $DIR/tests.xml
+
+pass=0
+fail=0
+XML=""
+
+function green {
+ (( pass += 1 ))
+ printf "$1: ${GREEN}$2${NC}\n"
+ XML+=" <testcase name=\"$1\"/>\n"
+}
+
+function yellow {
+ (( fail += 1 ))
+ printf "$1: ${YELLOW}$2${NC}\n"
+ XML+=" <testcase name=\"$1\">\n <error message=\"$2\">$2</error>\n </testcase>\n"
+}
+
+function red {
+ (( fail += 1 ))
+ printf "$1: ${RED}$2${NC}\n"
+ XML+=" <testcase name=\"$1\">\n <error message=\"$2\">$2</error>\n </testcase>\n"
+}
+
+function finish_suite {
+ printf "$1: Passed ${pass} out of $(( pass + fail ))\n"
+ XML=" <testsuite name=\"$1\" tests=\"$(( pass + fail ))\" failures=\"${fail}\" timestamp=\"$(date)\">\n$XML </testsuite>\n"
+ printf "$XML" >> $DIR/tests.xml
+ XML=""
+ pass=0
+ fail=0
+}
+
+SAILLIBDIR="$DIR"
+
+printf "<testsuites>\n" >> $DIR/tests.xml
+
+for i in `ls -d */`;
+do
+ cd $DIR/$i;
+ if $SAILDIR/sail -o out -ocaml ../prelude.sail `ls *.sail`;
+ then
+ ./out > result;
+ if diff expect result;
+ then
+ green "built $i" "ok"
+ else
+ yellow "bad output $i" "fail"
+ fi;
+ rm out;
+ rm result;
+ rm -r _sbuild
+ else
+ red "building $i" "fail"
+ fi
+done
+
+printf "</testsuites>\n" >> $DIR/tests.xml
diff --git a/test/ocaml/sail_lib.ml b/test/ocaml/sail_lib.ml
new file mode 100644
index 00000000..e287eadb
--- /dev/null
+++ b/test/ocaml/sail_lib.ml
@@ -0,0 +1,169 @@
+open Big_int
+
+type 'a return = { return : 'b . 'a -> 'b }
+
+let with_return (type t) (f : _ -> t) =
+ let module M =
+ struct exception Return of t end
+ in
+ let return = { return = (fun x -> raise (M.Return x)); } in
+ try f return with M.Return x -> x
+
+type bit = B0 | B1
+
+let and_bit = function
+ | B1, B1 -> B1
+ | _, _ -> B0
+
+let or_bit = function
+ | B0, B0 -> B0
+ | _, _ -> B1
+
+let and_vec (xs, ys) =
+ assert (List.length xs = List.length ys);
+ List.map2 (fun x y -> and_bit (x, y)) xs ys
+
+let and_bool (b1, b2) = b1 && b2
+
+let or_vec (xs, ys) =
+ assert (List.length xs = List.length ys);
+ List.map2 (fun x y -> or_bit (x, y)) xs ys
+
+let or_bool (b1, b2) = b1 || b2
+
+let undefined_bit () =
+ if Random.bool () then B0 else B1
+
+let undefined_bool () = Random.bool ()
+
+let rec undefined_vector (start_index, len, item) =
+ if eq_big_int len zero_big_int
+ then []
+ else item :: undefined_vector (start_index, sub_big_int len unit_big_int, item)
+
+let undefined_string () = ""
+
+let undefined_unit () = ()
+
+let undefined_int () =
+ big_int_of_int (Random.int 0xFFFF)
+
+let internal_pick list =
+ List.nth list (Random.int (List.length list))
+
+let eq_int (n, m) = eq_big_int n m
+
+let eq_string (str1, str2) = String.compare str1 str2 = 0
+
+let concat_string (str1, str2) = str1 ^ str2
+
+let rec drop n xs =
+ match n, xs with
+ | 0, xs -> xs
+ | n, [] -> []
+ | n, (x :: xs) -> drop (n -1) xs
+
+let rec take n xs =
+ match n, xs with
+ | 0, xs -> []
+ | n, (x :: xs) -> x :: take (n - 1) xs
+ | n, [] -> []
+
+let subrange (list, n, m) =
+ let n = int_of_big_int n in
+ let m = int_of_big_int m in
+ List.rev (take (n - (m - 1)) (drop m (List.rev list)))
+
+let eq_list (xs, ys) = List.for_all2 (fun x y -> x == y) xs ys
+
+let access (xs, n) = List.nth (List.rev xs) (int_of_big_int n)
+
+let append (xs, ys) = xs @ ys
+
+let update (xs, n, x) =
+ let n = int_of_big_int n in
+ take n xs @ [x] @ drop (n + 1) xs
+
+let update_subrange (xs, n, m, ys) =
+ let n = int_of_big_int n in
+ let m = int_of_big_int m in
+ assert false
+
+let length xs = big_int_of_int (List.length xs)
+
+let big_int_of_bit = function
+ | B0 -> zero_big_int
+ | B1 -> unit_big_int
+
+let uint xs =
+ let uint_bit x (n, pos) =
+ add_big_int n (mult_big_int (power_int_positive_int 2 pos) (big_int_of_bit x)), pos + 1
+ in
+ fst (List.fold_right uint_bit xs (zero_big_int, 0))
+
+let sint = function
+ | [] -> zero_big_int
+ | [msb] -> minus_big_int (big_int_of_bit msb)
+ | msb :: xs ->
+ let msb_pos = List.length xs in
+ let complement =
+ minus_big_int (mult_big_int (power_int_positive_int 2 msb_pos) (big_int_of_bit msb))
+ in
+ add_big_int complement (uint xs)
+
+let add (x, y) = add_big_int x y
+let sub (x, y) = sub_big_int x y
+let mult (x, y) = mult_big_int x y
+let quotient (x, y) = fst (quomod_big_int x y)
+let modulus (x, y) = snd (quomod_big_int x y)
+
+let add_bit_with_carry (x, y, carry) =
+ match x, y, carry with
+ | B0, B0, B0 -> B0, B0
+ | B0, B1, B0 -> B1, B0
+ | B1, B0, B0 -> B1, B0
+ | B1, B1, B0 -> B0, B1
+ | B0, B0, B1 -> B1, B0
+ | B0, B1, B1 -> B0, B1
+ | B1, B0, B1 -> B0, B1
+ | B1, B1, B1 -> B1, B1
+
+let not_bit = function
+ | B0 -> B1
+ | B1 -> B0
+
+let not_vec xs = List.map not_bit xs
+
+let add_vec_carry (xs, ys) =
+ assert (List.length xs = List.length ys);
+ let (carry, result) =
+ List.fold_right2 (fun x y (c, result) -> let (z, c) = add_bit_with_carry (x, y, c) in (c, z :: result)) xs ys (B0, [])
+ in
+ carry, result
+
+let add_vec (xs, ys) = snd (add_vec_carry (xs, ys))
+
+let rec replicate_bits (bits, n) =
+ if eq_big_int n zero_big_int
+ then []
+ else bits @ replicate_bits (bits, sub_big_int n unit_big_int)
+
+let identity x = x
+
+let get_slice_int (n, m, o) = assert false
+
+let hex_slice (str, n, m) = assert false
+
+let putchar n = print_endline (string_of_big_int n)
+
+let write_ram (addr_size, data_size, hex_ram, addr, data) =
+ assert false
+
+let read_ram (addr_size, data_size, hex_ram, addr) =
+ assert false
+
+(* FIXME: Casts can't be externed *)
+let zcast_unit_vec x = [x]
+
+let shl_int (n, m) = assert false
+let shr_int (n, m) = assert false
diff --git a/test/ocaml/string_equality/expect b/test/ocaml/string_equality/expect
new file mode 100644
index 00000000..27ba77dd
--- /dev/null
+++ b/test/ocaml/string_equality/expect
@@ -0,0 +1 @@
+true
diff --git a/test/ocaml/string_equality/string_equality.sail b/test/ocaml/string_equality/string_equality.sail
new file mode 100644
index 00000000..68629862
--- /dev/null
+++ b/test/ocaml/string_equality/string_equality.sail
@@ -0,0 +1,10 @@
+
+val unit -> unit effect pure main
+
+function main () = {
+ if ("test" == "test") then {
+ print("true")
+ } else {
+ print("false")
+ }
+}
diff --git a/test/typecheck/run_tests.sh b/test/typecheck/run_tests.sh
index 8e21eca0..e83cc20b 100755
--- a/test/typecheck/run_tests.sh
+++ b/test/typecheck/run_tests.sh
@@ -135,26 +135,26 @@ test_lem rtpass
finish_suite "Lem generation 2"
-function test_ocaml {
- for i in `ls $DIR/pass/`;
- do
- if $SAILDIR/sail -ocaml $DIR/$1/$i 2> /dev/null
- then
- green "generated ocaml for $1/$i" "pass"
+# function test_ocaml {
+# for i in `ls $DIR/pass/`;
+# do
+# if $SAILDIR/sail -ocaml $DIR/$1/$i 2> /dev/null
+# then
+# green "generated ocaml for $1/$i" "pass"
- rm $SAILDIR/${i%%.*}.ml
- else
- red "generated ocaml for $1/$i" "fail"
- fi
- done
-}
+# rm $SAILDIR/${i%%.*}.ml
+# else
+# red "generated ocaml for $1/$i" "fail"
+# fi
+# done
+# }
-test_ocaml pass
+# test_ocaml pass
-finish_suite "Ocaml generation 1"
+# finish_suite "Ocaml generation 1"
-test_ocaml rtpass
+# test_ocaml rtpass
-finish_suite "Ocaml generation 2"
+# finish_suite "Ocaml generation 2"
printf "</testsuites>\n" >> $DIR/tests.xml