src/HOL/Tools/SMT2/verit_proof.ML
changeset 57704 c0da3fc313e3
child 57705 5da48dae7d03
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/HOL/Tools/SMT2/verit_proof.ML	Wed Jul 30 14:03:12 2014 +0200
@@ -0,0 +1,135 @@
+(*  Title:      HOL/Tools/SMT2/verit_proof.ML
+    Author:     Mathias Fleury, ENS Rennes
+    Author:     Sascha Boehme, TU Muenchen
+
+VeriT proofs: parsing and abstract syntax tree.
+*)
+
+signature VERIT_PROOF =
+sig
+  (*proofs*)
+  datatype veriT_step = VeriT_Step of {
+    id: int,
+    rule: string,
+    prems: string list,
+    concl: term,
+    fixes: string list}
+
+  (*proof parser*)
+  val parse: typ Symtab.table -> term Symtab.table -> string list ->
+    Proof.context -> veriT_step list * Proof.context
+
+  val verit_step_prefix : string
+  val verit_proof_input_rule: string
+  val verit_rewrite : string
+end;
+
+structure VeriT_Proof: VERIT_PROOF =
+struct
+
+open SMTLIB2_Proof
+
+(* proof rules *)
+
+datatype veriT_node = VeriT_Node of {
+  id: int,
+  rule: string,
+  prems: string list,
+  concl: term,
+  bounds: string list}
+
+fun mk_node id rule prems concl bounds =
+  VeriT_Node {id = id, rule = rule, prems = prems, concl = concl, bounds = bounds}
+
+(*two structures needed*)
+datatype veriT_step = VeriT_Step of {
+  id: int,
+  rule: string,
+  prems: string list,
+  concl: term,
+  fixes: string list}
+
+fun mk_step id rule prems concl fixes =
+  VeriT_Step {id = id, rule = rule, prems = prems, concl = concl, fixes = fixes}
+
+val verit_step_prefix = ".c"
+val verit_proof_input_rule = "input"
+val verit_rewrite = "rewrite"
+
+(* proof parser *)
+
+fun node_of p cx =
+  ([], cx)
+  ||>> with_fresh_names (term_of p)
+  ||>> next_id
+  |>> (fn ((prems, (t, ns)), id) => mk_node id verit_proof_input_rule prems t ns)
+
+(*in order to get Z3-style quantification*)
+fun fix_quantification (SMTLIB2.S (SMTLIB2.Sym "forall" :: l)) =
+    let
+      val (quantified_vars, t) = split_last (map fix_quantification l)
+    in
+      SMTLIB2.S (SMTLIB2.Sym "forall" :: SMTLIB2.S quantified_vars :: t :: [])
+    end
+  | fix_quantification (SMTLIB2.S (SMTLIB2.Sym "exists" :: l)) =
+    let val (quantified_vars, t) = split_last (map fix_quantification l)
+    in
+      SMTLIB2.S (SMTLIB2.Sym "exists" :: SMTLIB2.S quantified_vars :: t :: [])
+    end
+  | fix_quantification (SMTLIB2.S l) = SMTLIB2.S (map fix_quantification l)
+  | fix_quantification x = x
+
+fun parse_proof cx =
+  let
+    fun rotate_pair (a, (b, c)) = ((a, b), c)
+    fun get_id (SMTLIB2.S [SMTLIB2.Sym "set", SMTLIB2.Sym id, SMTLIB2.S l]) = (id, l)
+      | get_id t = raise Fail ("unrecognized VeriT Proof" ^ PolyML.makestring t)
+    fun change_id_to_number x = (unprefix verit_step_prefix #> Int.fromString #> the) x
+    fun parse_rule (SMTLIB2.Sym rule :: l) = (rule, l)
+    fun parse_source (SMTLIB2.Key "clauses" :: SMTLIB2.S source ::l) =
+        (SOME (map (fn (SMTLIB2.Sym id) => id) source), l)
+      | parse_source l = (NONE, l)
+    fun skip_args (SMTLIB2.Key "args" :: SMTLIB2.S _ :: l) = l
+      | skip_args l = l
+
+    fun parse_conclusion [SMTLIB2.Key "conclusion", SMTLIB2.S concl] = concl
+
+    fun make_or_from_clausification l =
+      foldl1 (fn ((concl1, bounds1), (concl2, bounds2)) => (HOLogic.mk_disj (concl1, concl2),
+        bounds1 @ bounds2)) l
+    (*the conclusion is empty, ie no false*)
+    fun to_node ((((id, rule), prems), ([], cx))) = (mk_node id rule (the_default [] prems)
+          @{const False} [], cx)
+      | to_node ((((id, rule), prems), (concls, cx))) =
+        let val (concl, bounds) = make_or_from_clausification concls in
+          (mk_node id rule (the_default [] prems) concl bounds, cx) end
+  in
+    get_id
+    #>> change_id_to_number
+    ##> parse_rule
+    #> rotate_pair
+    ##> parse_source
+    #> rotate_pair
+    ##> skip_args
+    ##> parse_conclusion
+    ##> map fix_quantification
+    ##> (fn terms => fold_map (fn t => fn cx => node_of t cx) terms cx)
+    ##> apfst (map (fn (VeriT_Node {concl, bounds,...}) => (concl, bounds)))
+    #> to_node
+  end
+
+
+(* overall proof parser *)
+fun parse typs funs lines ctxt =
+  let
+    val (u, env) =
+     fold_map (fn l => fn cx => parse_proof cx l) (map (fn f => SMTLIB2.parse [f]) lines)
+     (empty_context ctxt typs funs)
+    val t =
+     map (fn (VeriT_Node {id, rule, prems, concl, bounds, ...}) =>
+       mk_step id rule prems concl bounds) u
+  in
+    (t, ctxt_of env)
+  end
+
+end;