diff options
-rw-r--r-- | fstar/Assumed.fst | 107 | ||||
-rw-r--r-- | fstar/Primitives.fst | 205 | ||||
-rw-r--r-- | rust-tests/src/main.rs | 19 | ||||
-rw-r--r-- | src/ExtractToFStar.ml | 28 |
4 files changed, 241 insertions, 118 deletions
diff --git a/fstar/Assumed.fst b/fstar/Assumed.fst deleted file mode 100644 index 584606ea..00000000 --- a/fstar/Assumed.fst +++ /dev/null @@ -1,107 +0,0 @@ -/// This file lists primitive and assumed functions and types, referenced by the -/// extraction mechanism. -module Assumed -open FStar.Mul - -#set-options "--z3rlimit 50 --fuel 0 --ifuel 1" - -/// Result type -type result (a : Type0) : Type0 = -| Return : a -> result a -| Fail : result a - -let isize_min : int = -9223372036854775808 -let isize_max : int = 9223372036854775807 -let i8_min : int = -128 -let i8_max : int = 127 -let i16_min : int = -32768 -let i16_max : int = 32767 -let i32_min : int = -2147483648 -let i32_max : int = 2147483647 -let i64_min : int = -9223372036854775808 -let i64_max : int = 9223372036854775807 -let i128_min : int = -170141183460469231731687303715884105728 -let i128_max : int = 170141183460469231731687303715884105727 -let usize_min : int = 0 -let usize_max : int = 18446744073709551615 -let u8_min : int = 0 -let u8_max : int = 255 -let u16_min : int = 0 -let u16_max : int = 65535 -let u32_min : int = 0 -let u32_max : int = 4294967295 -let u64_min : int = 0 -let u64_max : int = 18446744073709551615 -let u128_min : int = 0 -let u128_max : int = 340282366920938463463374607431768211455 - -type scalar_ty = -| Isize -| I8 -| I16 -| I32 -| I64 -| I128 -| Usize -| U8 -| U16 -| U32 -| U64 -| U128 - -let scalar_min (ty : scalar_ty) : int = - match ty with - | Isize -> isize_min - | I8 -> i8_min - | I16 -> i16_min - | I32 -> i32_min - | I64 -> i64_min - | I128 -> i128_min - | Usize -> usize_min - | U8 -> u8_min - | U16 -> u16_min - | U32 -> u32_min - | U64 -> u64_min - | U128 -> u128_min - -let scalar_max (ty : scalar_ty) : int = - match ty with - | Isize -> isize_max - | I8 -> i8_max - | I16 -> i16_max - | I32 -> i32_max - | I64 -> i64_max - | I128 -> i128_max - | Usize -> usize_max - | U8 -> u8_max - | U16 -> u16_max - | U32 -> u32_max - | U64 -> u64_max - | U128 -> u128_max - -type scalar (ty : scalar_ty) : Type0 = x:int{scalar_min ty <= x && x <= scalar_max ty} - -let mk_scalar (ty : scalar_ty) (x : int) : result (scalar ty) = - if scalar_min ty <= x && scalar_max ty >= x then Return x else Fail - -let g_neg (#ty : scalar_ty) (x : scalar ty) : result (scalar ty) = mk_scalar ty (-x) - -// TODO: remove -(*let g_lt (x : int) (y : int) = x <= y *) - -let g_div (#ty : scalar_ty) (x : scalar ty) (y : scalar ty) : result (scalar ty) = - if y <> 0 then mk_scalar ty (x / y) else Fail - -(* TODO: -let g_rem (#ty : scalar_ty) (x : scalar ty) (y : scalar ty) : result (scalar ty) = - if y <> 0 then mk_scalar ty (x / y) else Fail -*) - -let g_add (#ty : scalar_ty) (x : scalar ty) (y : scalar ty) : result (scalar ty) = - mk_scalar ty (x + y) - -let g_sub (#ty : scalar_ty) (x : scalar ty) (y : scalar ty) : result (scalar ty) = - mk_scalar ty (x - y) - -let g_mul (#ty : scalar_ty) (x : scalar ty) (y : scalar ty) : result (scalar ty) = - mk_scalar ty (x * y) diff --git a/fstar/Primitives.fst b/fstar/Primitives.fst new file mode 100644 index 00000000..1b3972cc --- /dev/null +++ b/fstar/Primitives.fst @@ -0,0 +1,205 @@ +/// This file lists primitive and assumed functions and types +module Primitives +open FStar.Mul + +#set-options "--z3rlimit 50 --fuel 0 --ifuel 1" + +(*** Result *) +type result (a : Type0) : Type0 = +| Return : a -> result a +| Fail : result a + +(*** Scalars *) +/// Rk.: most of the following code was at least partially generated +let isize_min : int = -9223372036854775808 +let isize_max : int = 9223372036854775807 +let i8_min : int = -128 +let i8_max : int = 127 +let i16_min : int = -32768 +let i16_max : int = 32767 +let i32_min : int = -2147483648 +let i32_max : int = 2147483647 +let i64_min : int = -9223372036854775808 +let i64_max : int = 9223372036854775807 +let i128_min : int = -170141183460469231731687303715884105728 +let i128_max : int = 170141183460469231731687303715884105727 +let usize_min : int = 0 +let usize_max : int = 18446744073709551615 +let u8_min : int = 0 +let u8_max : int = 255 +let u16_min : int = 0 +let u16_max : int = 65535 +let u32_min : int = 0 +let u32_max : int = 4294967295 +let u64_min : int = 0 +let u64_max : int = 18446744073709551615 +let u128_min : int = 0 +let u128_max : int = 340282366920938463463374607431768211455 + +type scalar_ty = +| Isize +| I8 +| I16 +| I32 +| I64 +| I128 +| Usize +| U8 +| U16 +| U32 +| U64 +| U128 + +let scalar_min (ty : scalar_ty) : int = + match ty with + | Isize -> isize_min + | I8 -> i8_min + | I16 -> i16_min + | I32 -> i32_min + | I64 -> i64_min + | I128 -> i128_min + | Usize -> usize_min + | U8 -> u8_min + | U16 -> u16_min + | U32 -> u32_min + | U64 -> u64_min + | U128 -> u128_min + +let scalar_max (ty : scalar_ty) : int = + match ty with + | Isize -> isize_max + | I8 -> i8_max + | I16 -> i16_max + | I32 -> i32_max + | I64 -> i64_max + | I128 -> i128_max + | Usize -> usize_max + | U8 -> u8_max + | U16 -> u16_max + | U32 -> u32_max + | U64 -> u64_max + | U128 -> u128_max + +type scalar (ty : scalar_ty) : Type0 = x:int{scalar_min ty <= x && x <= scalar_max ty} + +let mk_scalar (ty : scalar_ty) (x : int) : result (scalar ty) = + if scalar_min ty <= x && scalar_max ty >= x then Return x else Fail + +let scalar_neg (#ty : scalar_ty) (x : scalar ty) : result (scalar ty) = mk_scalar ty (-x) + +let scalar_div (#ty : scalar_ty) (x : scalar ty) (y : scalar ty) : result (scalar ty) = + if y <> 0 then mk_scalar ty (x / y) else Fail + +/// The remainder operation +let int_rem (x : int) (y : int{y <> 0}) : int = + if x >= 0 then (x % y) else -(x % y) + +(* Checking consistency with Rust *) +let _ = assert_norm(int_rem 1 2 = 1) +let _ = assert_norm(int_rem (-1) 2 = -1) +let _ = assert_norm(int_rem 1 (-2) = 1) +let _ = assert_norm(int_rem (-1) (-2) = -1) + +let scalar_rem (#ty : scalar_ty) (x : scalar ty) (y : scalar ty) : result (scalar ty) = + if y <> 0 then mk_scalar ty (int_rem x y) else Fail + +let scalar_add (#ty : scalar_ty) (x : scalar ty) (y : scalar ty) : result (scalar ty) = + mk_scalar ty (x + y) + +let scalar_sub (#ty : scalar_ty) (x : scalar ty) (y : scalar ty) : result (scalar ty) = + mk_scalar ty (x - y) + +let scalar_mul (#ty : scalar_ty) (x : scalar ty) (y : scalar ty) : result (scalar ty) = + mk_scalar ty (x * y) + +/// The scalar types +type isize = scalar Isize +type i8 = scalar I8 +type i16 = scalar I16 +type i32 = scalar I32 +type i64 = scalar I64 +type i128 = scalar I128 +type usize = scalar Usize +type u8 = scalar U8 +type u16 = scalar U16 +type u32 = scalar U32 +type u64 = scalar U64 +type u128 = scalar U128 + +/// Negation +let isize_neg = scalar_neg #Isize +let i8_neg = scalar_neg #I8 +let i16_neg = scalar_neg #I16 +let i32_neg = scalar_neg #I32 +let i64_neg = scalar_neg #I64 +let i128_neg = scalar_neg #I128 + +/// Division +let isize_div = scalar_div #Isize +let i8_div = scalar_div #I8 +let i16_div = scalar_div #I16 +let i32_div = scalar_div #I32 +let i64_div = scalar_div #I64 +let i128_div = scalar_div #I128 +let usize_div = scalar_div #Usize +let u8_div = scalar_div #U8 +let u16_div = scalar_div #U16 +let u32_div = scalar_div #U32 +let u64_div = scalar_div #U64 +let u128_div = scalar_div #U128 + +/// Remainder +let isize_rem = scalar_rem #Isize +let i8_rem = scalar_rem #I8 +let i16_rem = scalar_rem #I16 +let i32_rem = scalar_rem #I32 +let i64_rem = scalar_rem #I64 +let i128_rem = scalar_rem #I128 +let usize_rem = scalar_rem #Usize +let u8_rem = scalar_rem #U8 +let u16_rem = scalar_rem #U16 +let u32_rem = scalar_rem #U32 +let u64_rem = scalar_rem #U64 +let u128_rem = scalar_rem #U128 + +/// Addition +let isize_add = scalar_add #Isize +let i8_add = scalar_add #I8 +let i16_add = scalar_add #I16 +let i32_add = scalar_add #I32 +let i64_add = scalar_add #I64 +let i128_add = scalar_add #I128 +let usize_add = scalar_add #Usize +let u8_add = scalar_add #U8 +let u16_add = scalar_add #U16 +let u32_add = scalar_add #U32 +let u64_add = scalar_add #U64 +let u128_add = scalar_add #U128 + +/// Substraction +let isize_sub = scalar_sub #Isize +let i8_sub = scalar_sub #I8 +let i16_sub = scalar_sub #I16 +let i32_sub = scalar_sub #I32 +let i64_sub = scalar_sub #I64 +let i128_sub = scalar_sub #I128 +let usize_sub = scalar_sub #Usize +let u8_sub = scalar_sub #U8 +let u16_sub = scalar_sub #U16 +let u32_sub = scalar_sub #U32 +let u64_sub = scalar_sub #U64 +let u128_sub = scalar_sub #U128 + +/// Multiplication +let isize_mul = scalar_mul #Isize +let i8_mul = scalar_mul #I8 +let i16_mul = scalar_mul #I16 +let i32_mul = scalar_mul #I32 +let i64_mul = scalar_mul #I64 +let i128_mul = scalar_mul #I128 +let usize_mul = scalar_mul #Usize +let u8_mul = scalar_mul #U8 +let u16_mul = scalar_mul #U16 +let u32_mul = scalar_mul #U32 +let u64_mul = scalar_mul #U64 +let u128_mul = scalar_mul #U128 diff --git a/rust-tests/src/main.rs b/rust-tests/src/main.rs index 180ecdd6..125b0d76 100644 --- a/rust-tests/src/main.rs +++ b/rust-tests/src/main.rs @@ -13,6 +13,8 @@ fn main() { "Isize", "I8", "I16", "I32", "I64", "I128", "Usize", "U8", "U16", "U32", "U64", "U128", ]; + let can_fail_binops_lower = ["div", "rem", "add", "sub", "mul"]; + let mut ints_pairs = vec![]; for i in 0..ints_lower.len() { ints_pairs.push((&ints_lower[i], &ints_upper[i])); @@ -124,8 +126,25 @@ fn main() { } println!("\n"); + // Generate the scalar types for F* + for (lo, up) in &ints_pairs { + println!("type {} = scalar {}", lo, up); + } + println!("\n"); + + // Generate the unops (rk.: we need to manually filter `-` applied on + // unisgned numbers) + for binop in &can_fail_binops_lower { + for (lo, up) in &ints_pairs { + println!("let {}_{} = scalar_{} #{}", lo, binop, binop, up); + } + println!(""); + } + println!("\n"); + // Modulo tests test_modulo(1, 2); test_modulo(-1, 2); + test_modulo(1, -2); test_modulo(-1, -2); } diff --git a/src/ExtractToFStar.ml b/src/ExtractToFStar.ml index 3a5d2c7a..3ca003a4 100644 --- a/src/ExtractToFStar.ml +++ b/src/ExtractToFStar.ml @@ -92,34 +92,40 @@ let fstar_extract_binop (extract_expr : bool -> texpression -> unit) (fmt : F.formatter) (inside : bool) (binop : E.binop) (int_ty : integer_type) (arg0 : texpression) (arg1 : texpression) : unit = if inside then F.pp_print_string fmt "("; + (* Some binary operations have a special treatment *) (match binop with - | Eq -> + | Eq | Lt | Le | Ne | Ge | Gt -> + let binop = + match binop with + | Eq -> "=" + | Lt -> "<" + | Le -> "<=" + | Ne -> "<>" + | Ge -> ">=" + | Gt -> ">" + | _ -> failwith "Unreachable" + in extract_expr false arg0; F.pp_print_space fmt (); - F.pp_print_string fmt "="; + F.pp_print_string fmt binop; F.pp_print_space fmt (); extract_expr false arg1 - | _ -> + | Div | Rem | Add | Sub | Mul -> let binop = match binop with - | Eq -> failwith "Unreachable" - | Lt -> "lt" - | Le -> "le" - | Ne -> "ne" - | Ge -> "ge" - | Gt -> "gt" | Div -> "div" | Rem -> "rem" | Add -> "add" | Sub -> "sub" | Mul -> "mul" - | BitXor | BitAnd | BitOr | Shl | Shr -> raise Unimplemented + | _ -> failwith "Unreachable" in F.pp_print_string fmt (fstar_int_name int_ty ^ "_" ^ binop); F.pp_print_space fmt (); extract_expr false arg0; F.pp_print_space fmt (); - extract_expr false arg1); + extract_expr false arg1 + | BitXor | BitAnd | BitOr | Shl | Shr -> raise Unimplemented); if inside then F.pp_print_string fmt ")" (** |