(************************************************************************) (* * The Rocq Prover / The Rocq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* <O___,, * (see version control and CREDITS file for authors & dates) *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (* * (see LICENSE file for the text of the license) *) (************************************************************************)
open Constr
let bt_lib_constr n = lazy (UnivGen.constr_of_monomorphic_global (Global.env ()) @@ Rocqlib.lib_ref n)
module RocqList = struct let _nil = bt_lib_constr "core.list.nil" let _cons = bt_lib_constr "core.list.cons"
let cons ty h t = lapp _cons [|ty; h ; t|] let nil ty = lapp _nil [|ty|] let rec of_list ty = function
| [] -> nil ty
| t::q -> cons ty t (of_list ty q)
end
module RocqPositive = struct let _xH = bt_lib_constr "num.pos.xH" let _xO = bt_lib_constr "num.pos.xO" let _xI = bt_lib_constr "num.pos.xI"
(* A Rocq nat from an int *) let rec of_int n = if n <= 1 then Lazy.force _xH else let ans = of_int (n / 2) in if n mod 2 = 0 then lapp _xO [|ans|] else lapp _xI [|ans|]
end
module Env = struct
module ConstrHashtbl = Hashtbl.Make (Constr)
type t = (int ConstrHashtbl.t * int ref)
let add (tbl, off) (t : Constr.t) = try ConstrHashtbl.find tbl t with
| Not_found -> let i = !off in let () = ConstrHashtbl.add tbl t i in let () = incr off in
i
let empty () = (ConstrHashtbl.create 16, ref 1)
let to_list (env, _) = (* we need to get an ordered list *) let fold constr key accu = (key, constr) :: accu in let l = ConstrHashtbl.fold fold env [] in let sorted_l = List.sort (fun p1 p2 -> Int.compare (fst p1) (fst p2)) l in List.map snd sorted_l
end
module Bool = struct
let ind = lazy (Globnames.destIndRef (Rocqlib.lib_ref "core.bool.type")) let typ = bt_lib_constr "core.bool.type" let trueb = bt_lib_constr "core.bool.true" let falseb = bt_lib_constr "core.bool.false" let andb = bt_lib_constr "core.bool.andb" let orb = bt_lib_constr "core.bool.orb" let xorb = bt_lib_constr "core.bool.xorb" let negb = bt_lib_constr "core.bool.negb"
type t =
| Var of int
| Constofbool
| Andb of t * t
| Orb of t * t
| Xorb of t * t
| Negb of t
| Ifb of t * t * t
let quote (env : Env.t) genv sigma (c : Constr.t) : t = let trueb = Lazy.force trueb in let falseb = Lazy.force falseb in let andb = Lazy.force andb in let orb = Lazy.force orb in let xorb = Lazy.force xorb in let negb = Lazy.force negb in
let rec aux c = match decomp_term sigma c with
| App (head, args) -> if head === andb && Array.length args = 2 then
Andb (aux args.(0), aux args.(1)) elseif head === orb && Array.length args = 2 then
Orb (aux args.(0), aux args.(1)) elseif head === xorb && Array.length args = 2 then
Xorb (aux args.(0), aux args.(1)) elseif head === negb && Array.length args = 1 then
Negb (aux args.(0)) else Var (Env.add env c)
| Case (info, _, _, _, _, arg, pats) -> let is_bool = let i = info.ci_ind in
Environ.QInd.equal genv i (Lazy.force ind) in if is_bool then
Ifb ((aux arg), (aux (snd pats.(0))), (aux (snd pats.(1)))) else
Var (Env.add env c)
| _ -> if c === falseb thenConstfalse elseif c === trueb thenConsttrue else Var (Env.add env c) in
aux c
end
module Btauto = struct
open Pp
let eq = bt_lib_constr "core.eq.type"
let f_var = bt_lib_constr "plugins.btauto.f_var" let f_btm = bt_lib_constr "plugins.btauto.f_btm" let f_top = bt_lib_constr "plugins.btauto.f_top" let f_cnj = bt_lib_constr "plugins.btauto.f_cnj" let f_dsj = bt_lib_constr "plugins.btauto.f_dsj" let f_neg = bt_lib_constr "plugins.btauto.f_neg" let f_xor = bt_lib_constr "plugins.btauto.f_xor" let f_ifb = bt_lib_constr "plugins.btauto.f_ifb"
let eval = bt_lib_constr "plugins.btauto.eval" let witness = bt_lib_constr "plugins.btauto.witness" let soundness = bt_lib_constr "plugins.btauto.soundness"
let convert_env env : Constr.t =
RocqList.of_list (Lazy.force Bool.typ) env
let reify env t = lapp eval [|convert_env env; convert t|]
let print_counterexample env sigma p penv = let var = lapp witness [|p|] in let var = EConstr.of_constr var in (* Compute an assignment that dissatisfies the goal *) let redfun, _ = Redexpr.reduction_of_red_expr env Genredexpr.(CbvVm None) in let _, var = redfun env sigma var in let var = EConstr.Unsafe.to_constr var in let rec to_list l = match decomp_term sigma l with
| App (c, _)
when c === (Lazy.force RocqList._nil) -> []
| App (c, [|_; h; t|])
when c === (Lazy.force RocqList._cons) -> if h === (Lazy.force Bool.trueb) then (true :: to_list t) elseif h === (Lazy.force Bool.falseb) then (false :: to_list t) else invalid_arg "to_list"
| _ -> invalid_arg "to_list" in let concat sep = function
| [] -> mt ()
| h :: t -> let rec aux = function
| [] -> mt ()
| x :: t -> (sep ++ x ++ aux t) in
h ++ aux t in let var = to_list var in let len = List.length var in let penv = CList.firstn len penv in let assign = List.combine penv var in let map_msg (key,v) = let b = bool v in let term = Printer.pr_constr_env env sigma key in
term ++ spc () ++ str ":=" ++ spc () ++ b in let assign = List.map map_msg assign in let l = str "[" ++ (concat (str ";" ++ spc ()) assign) ++ str "]"in
str "Not a tautology:" ++ spc () ++ l
let print_counterexample p penv =
Proofview.Goal.enter beginfun gl -> let env = Proofview.Goal.env gl in let sigma = Proofview.Goal.sigma gl in let msg = lazy (print_counterexample env sigma p penv) in
Proofview.tclZERO ~info:(Exninfo.reify()) (Tacticals.FailError (0, msg)) end
let try_unification env =
Proofview.Goal.enter beginfun gl -> let concl = Proofview.Goal.concl gl in let eq = Lazy.force eq in let concl = EConstr.Unsafe.to_constr concl in let t = decomp_term (Tacmach.project gl) concl in match t with
| App (c, [|typ; p; _|]) when c === eq -> (* should be an equality [@eq poly ?p (Cst false)] *) let tac = Tacticals.tclORELSE0 Tactics.reflexivity (print_counterexample p env) in
tac
| _ -> let msg = str "Btauto: Internal error"in
Tacticals.tclFAIL msg end
let tac =
Proofview.Goal.enter beginfun gl -> let concl = Proofview.Goal.concl gl in let concl = EConstr.Unsafe.to_constr concl in let sigma = Tacmach.project gl in let eq = Lazy.force eq in letbool = Lazy.force Bool.typ in let t = decomp_term sigma concl in match t with
| App (c, [|typ; tl; tr|])
when typ === bool && c === eq -> let env = Env.empty () in let fl = Bool.quote env (Tacmach.pf_env gl) sigma tl in let fr = Bool.quote env (Tacmach.pf_env gl) sigma tr in let env = Env.to_list env in let fl = reify env fl in let fr = reify env fr in let changed_gl = Constr.mkApp (c, [|typ; fl; fr|]) in let changed_gl = EConstr.of_constr changed_gl in
Tacticals.tclTHENLIST [
Tactics.change_concl changed_gl;
Tactics.apply (EConstr.of_constr (Lazy.force soundness));
Tactics.normalise_vm_in_concl;
try_unification env
]
| _ -> let msg = str "Cannot recognize a boolean equality"in
Tacticals.tclFAIL msg end
end
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.