aboutsummaryrefslogtreecommitdiffstats
path: root/src/extraction/verit_checker.ml
diff options
context:
space:
mode:
authorChantal Keller <Chantal.Keller@inria.fr>2015-01-12 16:28:10 +0100
committerChantal Keller <Chantal.Keller@inria.fr>2015-01-12 16:28:10 +0100
commitcfb4587e26623318f432c7e3e21711afc2b966e7 (patch)
treea90c6f372633458aa0766510bcfdc4682eaa8f6a /src/extraction/verit_checker.ml
parent1e10dcc783b82269cc3fe3bb7419b9c1cc9e0fa7 (diff)
downloadsmtcoq-cfb4587e26623318f432c7e3e21711afc2b966e7.tar.gz
smtcoq-cfb4587e26623318f432c7e3e21711afc2b966e7.zip
Initial import of SMTCoq v1.2
Diffstat (limited to 'src/extraction/verit_checker.ml')
-rw-r--r--src/extraction/verit_checker.ml324
1 files changed, 324 insertions, 0 deletions
diff --git a/src/extraction/verit_checker.ml b/src/extraction/verit_checker.ml
new file mode 100644
index 0000000..e317dcf
--- /dev/null
+++ b/src/extraction/verit_checker.ml
@@ -0,0 +1,324 @@
+open SmtMisc
+open SmtCertif
+open SmtForm
+open SmtAtom
+open SmtTrace
+open Verit
+open Smtlib2_ast
+open Smtlib2_genConstr
+(* open Smt_checker *)
+
+
+module Mc = Micromega
+
+
+let mkInt = ExtrNative.of_int
+let mkArray = ExtrNative.of_array
+
+
+let rec dump_nat x =
+ match x with
+ | Mc.O -> Smt_checker.O
+ | Mc.S p -> Smt_checker.S (dump_nat p)
+
+
+let rec dump_positive x =
+ match x with
+ | Mc.XH -> Smt_checker.XH
+ | Mc.XO p -> Smt_checker.XO (dump_positive p)
+ | Mc.XI p -> Smt_checker.XI (dump_positive p)
+
+
+let dump_z x =
+ match x with
+ | Mc.Z0 -> Smt_checker.Z0
+ | Mc.Zpos p -> Smt_checker.Zpos (dump_positive p)
+ | Mc.Zneg p -> Smt_checker.Zneg (dump_positive p)
+
+
+let dump_pol e =
+ let rec dump_pol e =
+ match e with
+ | Mc.Pc n -> Smt_checker.Pc (dump_z n)
+ | Mc.Pinj(p,pol) -> Smt_checker.Pinj (dump_positive p, dump_pol pol)
+ | Mc.PX(pol1,p,pol2) -> Smt_checker.PX (dump_pol pol1, dump_positive p, dump_pol pol2) in
+ dump_pol e
+
+
+let dump_psatz e =
+ let rec dump_cone e =
+ match e with
+ | Mc.PsatzIn n -> Smt_checker.PsatzIn (dump_nat n)
+ | Mc.PsatzMulC(e,c) -> Smt_checker.PsatzMulC (dump_pol e, dump_cone c)
+ | Mc.PsatzSquare e -> Smt_checker.PsatzSquare (dump_pol e)
+ | Mc.PsatzAdd(e1,e2) -> Smt_checker.PsatzAdd (dump_cone e1, dump_cone e2)
+ | Mc.PsatzMulE(e1,e2) -> Smt_checker.PsatzMulE (dump_cone e1, dump_cone e2)
+ | Mc.PsatzC p -> Smt_checker.PsatzC (dump_z p)
+ | Mc.PsatzZ -> Smt_checker.PsatzZ in
+ dump_cone e
+
+
+let rec dump_list dump_elt l =
+ match l with
+ | [] -> Smt_checker.Nil
+ | e :: l -> Smt_checker.Cons (dump_elt e, dump_list dump_elt l)
+
+
+let rec dump_proof_term = function
+ | Micromega.DoneProof -> Smt_checker.DoneProof
+ | Micromega.RatProof(cone,rst) ->
+ Smt_checker.RatProof (dump_psatz cone, dump_proof_term rst)
+ | Micromega.CutProof(cone,prf) ->
+ Smt_checker.CutProof (dump_psatz cone, dump_proof_term prf)
+ | Micromega.EnumProof(c1,c2,prfs) ->
+ Smt_checker.EnumProof (dump_psatz c1, dump_psatz c2, dump_list dump_proof_term prfs)
+
+
+
+let to_coq to_lit confl =
+ let out_f f = to_lit f in
+ let out_c c = mkInt (get_pos c) in
+ let step_to_coq c =
+ match c.kind with
+ | Res res ->
+ let size = List.length res.rtail + 3 in
+ let args = Array.make size (mkInt 0) in
+ args.(0) <- mkInt (get_pos res.rc1);
+ args.(1) <- mkInt (get_pos res.rc2);
+ let l = ref res.rtail in
+ for i = 2 to size - 2 do
+ match !l with
+ | c::tl ->
+ args.(i) <- mkInt (get_pos c);
+ l := tl
+ | _ -> assert false
+ done;
+ Smt_checker.Euf_Checker.Res (mkInt (get_pos c), mkArray args)
+ | Other other ->
+ begin match other with
+ | ImmFlatten (c',f) -> Smt_checker.Euf_Checker.ImmFlatten (out_c c, out_c c', out_f f)
+ | True -> Smt_checker.Euf_Checker.CTrue (out_c c)
+ | False -> Smt_checker.Euf_Checker.CFalse (out_c c)
+ | BuildDef f -> Smt_checker.Euf_Checker.BuildDef (out_c c, out_f f)
+ | BuildDef2 f -> Smt_checker.Euf_Checker.BuildDef2 (out_c c, out_f f)
+ | BuildProj (f, i) -> Smt_checker.Euf_Checker.BuildProj (out_c c, out_f f, mkInt i)
+ | ImmBuildDef c' -> Smt_checker.Euf_Checker.ImmBuildDef (out_c c, out_c c')
+ | ImmBuildDef2 c' -> Smt_checker.Euf_Checker.ImmBuildDef2 (out_c c, out_c c')
+ | ImmBuildProj(c', i) -> Smt_checker.Euf_Checker.ImmBuildProj (out_c c, out_c c',mkInt i)
+ | EqTr (f, fl) ->
+ let res = List.fold_right (fun f l -> Smt_checker.Cons (out_f f, l)) fl Smt_checker.Nil in
+ Smt_checker.Euf_Checker.EqTr (out_c c, out_f f, res)
+ | EqCgr (f, fl) ->
+ let res = List.fold_right (fun f l -> Smt_checker.Cons ((match f with | Some f -> Smt_checker.Some (out_f f) | None -> Smt_checker.None), l)) fl Smt_checker.Nil in
+ Smt_checker.Euf_Checker.EqCgr (out_c c, out_f f, res)
+ | EqCgrP (f1, f2, fl) ->
+ let res = List.fold_right (fun f l -> Smt_checker.Cons ((match f with | Some f -> Smt_checker.Some (out_f f) | None -> Smt_checker.None), l)) fl Smt_checker.Nil in
+ Smt_checker.Euf_Checker.EqCgrP (out_c c, out_f f1, out_f f2, res)
+ | LiaMicromega (cl,d) ->
+ let cl' = List.fold_right (fun f l -> Smt_checker.Cons (out_f f, l)) cl Smt_checker.Nil in
+ let c' = List.fold_right (fun f l -> Smt_checker.Cons (dump_proof_term f, l)) d Smt_checker.Nil in
+ Smt_checker.Euf_Checker.LiaMicromega (out_c c, cl', c')
+ | LiaDiseq l -> Smt_checker.Euf_Checker.LiaDiseq (out_c c, out_f l)
+ | SplArith (orig,res,l) ->
+ let res' = out_f res in
+ let l' = List.fold_right (fun f l -> Smt_checker.Cons (dump_proof_term f, l)) l Smt_checker.Nil in
+ Smt_checker.Euf_Checker.SplArith (out_c c, out_c orig, res', l')
+ | SplDistinctElim (c',f) -> Smt_checker.Euf_Checker.SplDistinctElim (out_c c, out_c c', out_f f)
+ end
+ | _ -> assert false in
+ let def_step =
+ Smt_checker.Euf_Checker.Res (mkInt 0, mkArray [|mkInt 0|]) in
+ let r = ref confl in
+ let nc = ref 0 in
+ while not (isRoot !r.kind) do r := prev !r; incr nc done;
+ let last_root = !r in
+ let size = !nc in
+ let max = (Parray.trunc_size (Uint63.of_int 4194303)) - 1 in
+ let q,r1 = size / max, size mod max in
+
+ let trace =
+ let len = if r1 = 0 then q + 1 else q + 2 in
+ Array.make len (mkArray [|def_step|]) in
+ for j = 0 to q - 1 do
+ let tracej = Array.make (Parray.trunc_size (Uint63.of_int 4194303)) def_step in
+ for i = 0 to max - 1 do
+ r := next !r;
+ tracej.(i) <- step_to_coq !r;
+ done;
+ trace.(j) <- mkArray tracej
+ done;
+ if r1 <> 0 then begin
+ let traceq = Array.make (r1 + 1) def_step in
+ for i = 0 to r1-1 do
+ r := next !r;
+ traceq.(i) <- step_to_coq !r;
+ done;
+ trace.(q) <- mkArray traceq
+ end;
+
+ (mkArray trace, last_root)
+
+
+let btype_to_coq = function
+ | TZ -> Smt_checker.Typ.TZ
+ | Tbool -> Smt_checker.Typ.Tbool
+ | Tpositive -> Smt_checker.Typ.Tpositive
+ | Tindex i -> Smt_checker.Typ.Tindex (mkInt (SmtAtom.indexed_type_index i))
+
+
+let c_to_coq = function
+ | CO_xH -> Smt_checker.Atom.CO_xH
+ | CO_Z0 -> Smt_checker.Atom.CO_Z0
+
+
+let u_to_coq = function
+ | UO_xO -> Smt_checker.Atom.UO_xO
+ | UO_xI -> Smt_checker.Atom.UO_xI
+ | UO_Zpos -> Smt_checker.Atom.UO_Zpos
+ | UO_Zneg -> Smt_checker.Atom.UO_Zneg
+ | UO_Zopp -> Smt_checker.Atom.UO_Zopp
+
+
+let b_to_coq = function
+ | BO_Zplus -> Smt_checker.Atom.BO_Zplus
+ | BO_Zminus -> Smt_checker.Atom.BO_Zminus
+ | BO_Zmult -> Smt_checker.Atom.BO_Zmult
+ | BO_Zlt -> Smt_checker.Atom.BO_Zlt
+ | BO_Zle -> Smt_checker.Atom.BO_Zle
+ | BO_Zge -> Smt_checker.Atom.BO_Zge
+ | BO_Zgt -> Smt_checker.Atom.BO_Zgt
+ | BO_eq t -> Smt_checker.Atom.BO_eq (btype_to_coq t)
+
+
+let n_to_coq = function
+ | NO_distinct t -> btype_to_coq t
+
+
+let i_to_coq i = mkInt (SmtAtom.indexed_op_index i)
+
+
+let a_to_coq a =
+ let to_coq h = mkInt (Atom.index h) in
+ match a with
+ | Acop op -> Smt_checker.Atom.Acop (c_to_coq op)
+ | Auop (op,h) -> Smt_checker.Atom.Auop (u_to_coq op, to_coq h)
+ | Abop (op,h1,h2) ->
+ Smt_checker.Atom.Abop (b_to_coq op, to_coq h1, to_coq h2)
+ | Anop (op,ha) ->
+ let cop = n_to_coq op in
+ let cargs = Array.fold_right (fun h l -> Smt_checker.Cons (to_coq h, l)) ha Smt_checker.Nil in
+ Smt_checker.Atom.Anop (cop, cargs)
+ | Aapp (op,args) ->
+ let cop = i_to_coq op in
+ let cargs = Array.fold_right (fun h l -> Smt_checker.Cons (to_coq h, l)) args Smt_checker.Nil in
+ Smt_checker.Atom.Aapp (cop, cargs)
+
+
+let atom_interp_tbl reify =
+ let t = Atom.to_array reify (Smt_checker.Atom.Acop Smt_checker.Atom.CO_xH) a_to_coq in
+ mkArray t
+
+
+let form_to_coq hf = mkInt (Form.to_lit hf)
+
+let args_to_coq args =
+ let cargs = Array.make (Array.length args + 1) (mkInt 0) in
+ Array.iteri (fun i hf -> cargs.(i) <- form_to_coq hf) args;
+ mkArray cargs
+
+let pf_to_coq = function
+ | Fatom a -> Smt_checker.Form.Fatom (mkInt (Atom.index a))
+ | Fapp(op,args) ->
+ match op with
+ | Ftrue -> Smt_checker.Form.Ftrue
+ | Ffalse -> Smt_checker.Form.Ffalse
+ | Fand -> Smt_checker.Form.Fand (args_to_coq args)
+ | For -> Smt_checker.Form.For (args_to_coq args)
+ | Fimp -> Smt_checker.Form.Fimp (args_to_coq args)
+ | Fxor -> if Array.length args = 2 then Smt_checker.Form.Fxor (form_to_coq args.(0), form_to_coq args.(1)) else assert false
+ | Fiff -> if Array.length args = 2 then Smt_checker.Form.Fiff (form_to_coq args.(0), form_to_coq args.(1)) else assert false
+ | Fite -> if Array.length args = 3 then Smt_checker.Form.Fite (form_to_coq args.(0), form_to_coq args.(1), form_to_coq args.(2)) else assert false
+ | Fnot2 i -> Smt_checker.Form.Fnot2 (mkInt i, form_to_coq args.(0))
+
+
+let form_interp_tbl reify =
+ let (_,t) = Form.to_array reify Smt_checker.Form.Ftrue pf_to_coq in
+ mkArray t
+
+
+(* Importing from SMT-LIB v.2 without generating section variables *)
+
+let count_btype = ref 0
+let count_op = ref 0
+
+
+let declare_sort sym =
+ let s = string_of_symbol sym in
+ let res = Tindex (dummy_indexed_type !count_btype) in
+ incr count_btype;
+ VeritSyntax.add_btype s res;
+ res
+
+
+let declare_fun sym arg cod =
+ let s = string_of_symbol sym in
+ let tyl = List.map sort_of_sort arg in
+ let ty = sort_of_sort cod in
+ let op = dummy_indexed_op !count_op (Array.of_list (List.map fst tyl)) (fst ty) in
+ incr count_op;
+ VeritSyntax.add_fun s op;
+ op
+
+
+let declare_commands ra rf acc = function
+ | CDeclareSort (_,sym,_) -> let _ = declare_sort sym in acc
+ | CDeclareFun (_,sym, (_, arg), cod) -> let _ = declare_fun sym arg cod in acc
+ | CAssert (_, t) -> (make_root ra rf t)::acc
+ | _ -> acc
+
+
+let import_smtlib2 ra rf filename =
+ let chan = open_in filename in
+ let lexbuf = Lexing.from_channel chan in
+ let commands = Smtlib2_parse.main Smtlib2_lex.token lexbuf in
+ close_in chan;
+ match commands with
+ | None -> []
+ | Some (Smtlib2_ast.Commands (_,(_,res))) ->
+ List.rev (List.fold_left (declare_commands ra rf) [] res)
+
+
+(* The final checker *)
+
+let this_clear_all () =
+ Verit.clear_all ();
+ count_btype := 0;
+ count_op := 0
+
+
+let checker fsmt fproof =
+ this_clear_all ();
+ let ra = VeritSyntax.ra in
+ let rf = VeritSyntax.rf in
+ let roots = import_smtlib2 ra rf fsmt in
+ let (max_id, confl) = import_trace fproof None in
+ let (tres,last_root) = to_coq (fun i -> mkInt (SmtAtom.Form.to_lit i)) confl in
+ let certif =
+ Smt_checker.Euf_Checker.Certif (mkInt (max_id + 1), tres, mkInt (get_pos confl)) in
+ let used_roots = compute_roots roots last_root in
+ let used_rootsCstr =
+ let l = List.length used_roots in
+ let res = Array.make (l + 1) (mkInt 0) in
+ let i = ref (l-1) in
+ List.iter (fun j -> res.(!i) <- mkInt j; decr i) used_roots;
+ Smt_checker.Some (mkArray res) in
+ let rootsCstr =
+ let res = Array.make (List.length roots + 1) (mkInt 0) in
+ let i = ref 0 in
+ List.iter (fun j -> res.(!i) <- mkInt (SmtAtom.Form.to_lit j); incr i) roots;
+ mkArray res in
+
+ let t_atom = atom_interp_tbl ra in
+ let t_form = form_interp_tbl rf in
+
+ Smt_checker.Euf_Checker.checker_ext t_atom t_form rootsCstr used_rootsCstr certif