(** Why3 driver for Z3 >= 4.4 *)

prelude ";; produced by z3_gnatprove.drv ;;"
(* no set-logic for Z3 *)
prelude "(set-info :source |VC generated by SPARK 2014|)"
prelude "(set-info :smt-lib-version 2.0)"
prelude "(set-info :category industrial)"
prelude "(set-info :status unknown)"
prelude "(set-option :smt.mbqi false)"
prelude "(set-option :smt.macro-finder true)"

import "smt-libv2.gen"
import "smt-libv2-bv.gen"
import "smt-libv2-floats.gen"
import "discrimination.gen"
printer "smtv2"

(* Counterexamples: set model parser *)
model_parser "smtv2"

transformation "inline_trivial"
transformation "eliminate_builtin"
transformation "detect_polymorphism"
transformation "eliminate_inductive"
transformation "eliminate_algebraic_if_poly"
transformation "eliminate_epsilon"

(* remove pointless quantifiers from the goal *)
transformation "introduce_premises"
transformation "fold_defs"

transformation "simplify_formula"
(*transformation "simplify_trivial_quantification"*)

(* Prepare for counter-example query: get rid of some quantifiers (makes it
possible to query model values of the variables in premises) and introduce
counter-example projections  *)
transformation "prepare_for_counterexmp"

transformation "eliminate_quantifiers"

transformation "discriminate_if_poly"
transformation "encoding_smt_if_poly"

(** Error messages specific to Z3 *)

outofmemory "(error \".*out of memory\")\\|Cannot allocate memory\\|Maximal allocation counts .* have been exceeded\\|(error \".*number of configured allocations exceeded\")"
timeout "interrupted by timeout"
steps ":rlimit-count.*\\([0-9]+.?[0-9]*\\)" 1

(** Extra theories supported by Z3 *)

(* float literals  *)
theory "_gnatprove_standard".Floating
  syntax function rem "(fp.rem %1 %2)"
end

theory "_gnatprove_standard".Float32_next_prev
  remove prop max_value

  syntax function max_value "(fp #b0 #b11111110 #b11111111111111111111111)"
end

theory "_gnatprove_standard".Float64_next_prev
  remove prop max_value

  syntax function max_value "(fp #b0 #b11111111110 #b1111111111111111111111111111111111111111111111111111)"
end

theory "_gnatprove_standard".Float32
  syntax function one "(fb #b0 #b01111111 #b00000000000000000000000)"
  remove allprops
end

theory "_gnatprove_standard".Float64
  syntax function one "(fb #b0 #b01111111111 #b0000000000000000000000000000000000000000000000000000)"
  remove allprops
end

theory ieee_float.Float64
(* check the sign bit; if pos |%1| else |%1| - 2^1025 *)
   syntax function to_int
     "(ite (= ((_ extract 1024 1024) ((_ fp.to_sbv 1025) %1 %2)) #b0) (bv2int ((_ fp.to_sbv 1025) %1 %2)) (- (bv2int ((_ fp.to_sbv 1025) %1 %2)) (bv2int (bvshl (_ bv1 1026) (_ bv1025 1026)))))"
     (* we do not translate of_int since z3 will not prove anything if it appears in its context, see PC07-014 *)
end

theory ieee_float.Float32
  (* check the sign bit; if pos |%1| else |%1| - 2^129 *)
   syntax function to_int
     "(ite (= ((_ extract 128 128) ((_ fp.to_sbv 129) %1 %2)) #b0) (bv2int ((_ fp.to_sbv 129) %1 %2)) (- (bv2int ((_ fp.to_sbv 129) %1 %2)) (bv2int (bvshl (_ bv1 130) (_ bv129 130)))))"
end

theory real.Square
  remove allprops
end

(* bitvector theories are not in smt-libv2.drv since cvc4 and z3 don't
   have the same name for the function to_uint *)
theory bv.BV_Gen
  syntax function to_uint "(bv2int %1)"

  remove allprops
end

theory bv.BV128
  syntax function of_int "((_ int2bv 128) %1)"
end

theory bv.BV64
  syntax function of_int "((_ int2bv 64) %1)"
end

theory bv.BV32
  syntax function of_int "((_ int2bv 32) %1)"
end

theory bv.BV16
  syntax function of_int "((_ int2bv 16) %1)"
end

theory bv.BV8
  syntax function of_int "((_ int2bv 8) %1)"
end

(**********************************************************************
 ***                       gnat2why theories                        ***
 **********************************************************************)

theory _gnatprove_standard_th.Integer
   syntax function bool_eq "(= %1 %2)"
   syntax function bool_ne "(not (= %1 %2))"
   syntax function bool_lt "(< %1 %2)"
   syntax function bool_le "(<= %1 %2)"
   syntax function bool_gt "(> %1 %2)"
   syntax function bool_ge "(>= %1 %2)"

   remove allprops
end

theory _gnatprove_standard_th.Boolean_Func
   syntax function bool_eq "(= %1 %2)"
   remove allprops
end

theory ada__model_th.Discrete_Base_Theory
   syntax function bool_eq "(= %1 %2)"
   remove allprops
end

theory _gnatprove_standard.BVAda
   syntax function bool_eq "(= %1 %2)"
   syntax function bool_ne "(not (= %1 %2))"
   syntax function bool_lt "(bvult %1 %2)"
   syntax function bool_le "(bvule %1 %2)"
   syntax function bool_gt "(bvugt %1 %2)"
   syntax function bool_ge "(bvuge %1 %2)"

   remove allprops
end
