src/HOL/Tools/SMT2/smtlib2_proof.ML
changeset 58061 3d060f43accb
parent 58060 835b5443b978
child 58062 f4d8987656b9
--- a/src/HOL/Tools/SMT2/smtlib2_proof.ML	Thu Aug 28 00:40:38 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,298 +0,0 @@
-(*  Title:      HOL/Tools/SMT2/smtlib2_proof.ML
-    Author:     Sascha Boehme, TU Muenchen
-    Author:     Mathias Fleury, ENS Rennes
-    Author:     Jasmin Blanchette, TU Muenchen
-
-SMT-LIB-2-style proofs: parsing and abstract syntax tree.
-*)
-
-signature SMTLIB2_PROOF =
-sig
-  datatype 'b shared = Tree of SMTLIB2.tree | Term of term | Proof of 'b | None
-  type ('a, 'b) context
-
-  val mk_context: Proof.context -> int -> 'b shared Symtab.table -> typ Symtab.table ->
-    term Symtab.table -> 'a -> ('a, 'b) context
-  val empty_context: Proof.context -> typ Symtab.table -> term Symtab.table -> ('a list, 'b) context
-  val ctxt_of: ('a, 'b) context -> Proof.context
-  val lookup_binding: ('a, 'b) context -> string -> 'b shared
-  val update_binding: string * 'b shared -> ('a, 'b) context -> ('a, 'b) context
-  val with_bindings: (string * 'b shared) list -> (('a, 'b) context -> 'c * ('d, 'b) context) ->
-    ('a, 'b) context -> 'c * ('d, 'b) context
-  val next_id: ('a, 'b) context -> int * ('a, 'b) context
-  val with_fresh_names: (('a list, 'b) context ->
-    term * ((string * (string * typ)) list, 'b) context) -> ('c, 'b) context -> (term * string list)
-
-  (*type and term parsers*)
-  type type_parser = SMTLIB2.tree * typ list -> typ option
-  type term_parser = SMTLIB2.tree * term list -> term option
-  val add_type_parser: type_parser -> Context.generic -> Context.generic
-  val add_term_parser: term_parser -> Context.generic -> Context.generic
-
-  exception SMTLIB2_PARSE of string * SMTLIB2.tree
-
-  val declare_fun: string -> typ -> ((string * typ) list, 'a) context ->
-    ((string * typ) list, 'a) context
-  val dest_binding: SMTLIB2.tree -> string * 'a shared
-  val type_of: ('a, 'b) context -> SMTLIB2.tree -> typ
-  val term_of: SMTLIB2.tree -> ((string * (string * typ)) list, 'a) context ->
-    term * ((string * (string * typ)) list, 'a) context
-end;
-
-structure SMTLIB2_Proof: SMTLIB2_PROOF =
-struct
-
-(* proof parser context *)
-
-datatype 'b shared = Tree of SMTLIB2.tree | Term of term | Proof of 'b | None
-
-type ('a, 'b) context = {
-  ctxt: Proof.context,
-  id: int,
-  syms: 'b shared Symtab.table,
-  typs: typ Symtab.table,
-  funs: term Symtab.table,
-  extra: 'a}
-
-fun mk_context ctxt id syms typs funs extra: ('a, 'b) context =
-  {ctxt = ctxt, id = id, syms = syms, typs = typs, funs = funs, extra = extra}
-
-fun empty_context ctxt typs funs = mk_context ctxt 1 Symtab.empty typs funs []
-
-fun ctxt_of ({ctxt, ...}: ('a, 'b) context) = ctxt
-
-fun lookup_binding ({syms, ...}: ('a, 'b) context) =
-  the_default None o Symtab.lookup syms
-
-fun map_syms f ({ctxt, id, syms, typs, funs, extra}: ('a, 'b) context) =
-  mk_context ctxt id (f syms) typs funs extra
-
-fun update_binding b = map_syms (Symtab.update b)
-
-fun with_bindings bs f cx =
-  let val bs' = map (lookup_binding cx o fst) bs
-  in
-    cx
-    |> fold update_binding bs
-    |> f
-    ||> fold2 (fn (name, _) => update_binding o pair name) bs bs'
-  end
-
-fun next_id ({ctxt, id, syms, typs, funs, extra}: ('a, 'b) context) =
-  (id, mk_context ctxt (id + 1) syms typs funs extra)
-
-fun with_fresh_names f ({ctxt, id, syms, typs, funs, ...}: ('a, 'b) context) =
-  let
-    fun bind (_, v as (_, T)) t = Logic.all_const T $ Term.absfree v t
-
-    val needs_inferT = equal Term.dummyT orf Term.is_TVar
-    val needs_infer = Term.exists_type (Term.exists_subtype needs_inferT)
-    fun infer_types ctxt =
-      singleton (Type_Infer_Context.infer_types ctxt) #>
-      singleton (Proof_Context.standard_term_check_finish ctxt)
-    fun infer ctxt t = if needs_infer t then infer_types ctxt t else t
-
-    val (t, {ctxt = ctxt', extra = names, ...}: ((string * (string * typ)) list, 'b) context) =
-      f (mk_context ctxt id syms typs funs [])
-    val t' = infer ctxt' (fold_rev bind names (HOLogic.mk_Trueprop t))
-  in
-    (t', map fst names)
-  end
-
-fun lookup_typ ({typs, ...}: ('a, 'b) context) = Symtab.lookup typs
-fun lookup_fun ({funs, ...}: ('a, 'b) context) = Symtab.lookup funs
-
-
-(* core type and term parser *)
-
-fun core_type_parser (SMTLIB2.Sym "Bool", []) = SOME @{typ HOL.bool}
-  | core_type_parser (SMTLIB2.Sym "Int", []) = SOME @{typ Int.int}
-  | core_type_parser _ = NONE
-
-fun mk_unary n t =
-  let val T = fastype_of t
-  in Const (n, T --> T) $ t end
-
-fun mk_binary' n T U t1 t2 = Const (n, [T, T] ---> U) $ t1 $ t2
-
-fun mk_binary n t1 t2 =
-  let val T = fastype_of t1
-  in mk_binary' n T T t1 t2 end
-
-fun mk_rassoc f t ts =
-  let val us = rev (t :: ts)
-  in fold f (tl us) (hd us) end
-
-fun mk_lassoc f t ts = fold (fn u1 => fn u2 => f u2 u1) ts t
-
-fun mk_lassoc' n = mk_lassoc (mk_binary n)
-
-fun mk_binary_pred n S t1 t2 =
-  let
-    val T1 = fastype_of t1
-    val T2 = fastype_of t2
-    val T =
-      if T1 <> Term.dummyT then T1
-      else if T2 <> Term.dummyT then T2
-      else TVar (("?a", serial ()), S)
-  in mk_binary' n T @{typ HOL.bool} t1 t2 end
-
-fun mk_less t1 t2 = mk_binary_pred @{const_name ord_class.less} @{sort linorder} t1 t2
-fun mk_less_eq t1 t2 = mk_binary_pred @{const_name ord_class.less_eq} @{sort linorder} t1 t2
-
-fun core_term_parser (SMTLIB2.Sym "true", _) = SOME @{const HOL.True}
-  | core_term_parser (SMTLIB2.Sym "false", _) = SOME @{const HOL.False}
-  | core_term_parser (SMTLIB2.Sym "not", [t]) = SOME (HOLogic.mk_not t)
-  | core_term_parser (SMTLIB2.Sym "and", t :: ts) = SOME (mk_rassoc (curry HOLogic.mk_conj) t ts)
-  | core_term_parser (SMTLIB2.Sym "or", t :: ts) = SOME (mk_rassoc (curry HOLogic.mk_disj) t ts)
-  | core_term_parser (SMTLIB2.Sym "=>", [t1, t2]) = SOME (HOLogic.mk_imp (t1, t2))
-  | core_term_parser (SMTLIB2.Sym "implies", [t1, t2]) = SOME (HOLogic.mk_imp (t1, t2))
-  | core_term_parser (SMTLIB2.Sym "=", [t1, t2]) = SOME (HOLogic.mk_eq (t1, t2))
-  | core_term_parser (SMTLIB2.Sym "~", [t1, t2]) = SOME (HOLogic.mk_eq (t1, t2))
-  | core_term_parser (SMTLIB2.Sym "ite", [t1, t2, t3]) =
-      let
-        val T = fastype_of t2
-        val c = Const (@{const_name HOL.If}, [@{typ HOL.bool}, T, T] ---> T)
-      in SOME (c $ t1 $ t2 $ t3) end
-  | core_term_parser (SMTLIB2.Num i, []) = SOME (HOLogic.mk_number @{typ Int.int} i)
-  | core_term_parser (SMTLIB2.Sym "-", [t]) = SOME (mk_unary @{const_name uminus_class.uminus} t)
-  | core_term_parser (SMTLIB2.Sym "~", [t]) = SOME (mk_unary @{const_name uminus_class.uminus} t)
-  | core_term_parser (SMTLIB2.Sym "+", t :: ts) =
-      SOME (mk_lassoc' @{const_name plus_class.plus} t ts)
-  | core_term_parser (SMTLIB2.Sym "-", t :: ts) =
-      SOME (mk_lassoc' @{const_name minus_class.minus} t ts)
-  | core_term_parser (SMTLIB2.Sym "*", t :: ts) =
-      SOME (mk_lassoc' @{const_name times_class.times} t ts)
-  | core_term_parser (SMTLIB2.Sym "div", [t1, t2]) = SOME (mk_binary @{const_name z3div} t1 t2)
-  | core_term_parser (SMTLIB2.Sym "mod", [t1, t2]) = SOME (mk_binary @{const_name z3mod} t1 t2)
-  | core_term_parser (SMTLIB2.Sym "<", [t1, t2]) = SOME (mk_less t1 t2)
-  | core_term_parser (SMTLIB2.Sym ">", [t1, t2]) = SOME (mk_less t2 t1)
-  | core_term_parser (SMTLIB2.Sym "<=", [t1, t2]) = SOME (mk_less_eq t1 t2)
-  | core_term_parser (SMTLIB2.Sym ">=", [t1, t2]) = SOME (mk_less_eq t2 t1)
-  | core_term_parser _ = NONE
-
-
-(* custom type and term parsers *)
-
-type type_parser = SMTLIB2.tree * typ list -> typ option
-
-type term_parser = SMTLIB2.tree * term list -> term option
-
-fun id_ord ((id1, _), (id2, _)) = int_ord (id1, id2)
-
-structure Parsers = Generic_Data
-(
-  type T = (int * type_parser) list * (int * term_parser) list
-  val empty : T = ([(serial (), core_type_parser)], [(serial (), core_term_parser)])
-  val extend = I
-  fun merge ((tys1, ts1), (tys2, ts2)) =
-    (Ord_List.merge id_ord (tys1, tys2), Ord_List.merge id_ord (ts1, ts2))
-)
-
-fun add_type_parser type_parser =
-  Parsers.map (apfst (Ord_List.insert id_ord (serial (), type_parser)))
-
-fun add_term_parser term_parser =
-  Parsers.map (apsnd (Ord_List.insert id_ord (serial (), term_parser)))
-
-fun get_type_parsers ctxt = map snd (fst (Parsers.get (Context.Proof ctxt)))
-fun get_term_parsers ctxt = map snd (snd (Parsers.get (Context.Proof ctxt)))
-
-fun apply_parsers parsers x =
-  let
-    fun apply [] = NONE
-      | apply (parser :: parsers) =
-          (case parser x of
-            SOME y => SOME y
-          | NONE => apply parsers)
-  in apply parsers end
-
-
-(* type and term parsing *)
-
-exception SMTLIB2_PARSE of string * SMTLIB2.tree
-
-val desymbolize = Name.desymbolize (SOME false) o perhaps (try (unprefix "?"))
-
-fun fresh_fun add name n T ({ctxt, id, syms, typs, funs, extra}: ('a, 'b) context) =
-  let
-    val (n', ctxt') = yield_singleton Variable.variant_fixes n ctxt
-    val t = Free (n', T)
-    val funs' = Symtab.update (name, t) funs
-  in (t, mk_context ctxt' id syms typs funs' (add (n', T) extra)) end
-
-fun declare_fun name = snd oo fresh_fun cons name (desymbolize name)
-fun declare_free name = fresh_fun (cons o pair name) name (desymbolize name)
-
-fun parse_type cx ty Ts =
-  (case apply_parsers (get_type_parsers (ctxt_of cx)) (ty, Ts) of
-    SOME T => T
-  | NONE =>
-      (case ty of
-        SMTLIB2.Sym name =>
-          (case lookup_typ cx name of
-            SOME T => T
-          | NONE => raise SMTLIB2_PARSE ("unknown SMT type", ty))
-      | _ => raise SMTLIB2_PARSE ("bad SMT type format", ty)))
-
-fun parse_term t ts cx =
-  (case apply_parsers (get_term_parsers (ctxt_of cx)) (t, ts) of
-    SOME u => (u, cx)
-  | NONE =>
-      (case t of
-        SMTLIB2.Sym name =>
-          (case lookup_fun cx name of
-            SOME u => (Term.list_comb (u, ts), cx)
-          | NONE =>
-              if null ts then declare_free name Term.dummyT cx
-              else raise SMTLIB2_PARSE ("bad SMT term", t))
-      | _ => raise SMTLIB2_PARSE ("bad SMT term format", t)))
-
-fun type_of cx ty =
-  (case try (parse_type cx ty) [] of
-    SOME T => T
-  | NONE =>
-      (case ty of
-        SMTLIB2.S (ty' :: tys) => parse_type cx ty' (map (type_of cx) tys)
-      | _ => raise SMTLIB2_PARSE ("bad SMT type", ty)))
-
-fun dest_var cx (SMTLIB2.S [SMTLIB2.Sym name, ty]) = (name, (desymbolize name, type_of cx ty))
-  | dest_var _ v = raise SMTLIB2_PARSE ("bad SMT quantifier variable format", v)
-
-fun dest_body (SMTLIB2.S (SMTLIB2.Sym "!" :: body :: _)) = dest_body body
-  | dest_body body = body
-
-fun dest_binding (SMTLIB2.S [SMTLIB2.Sym name, t]) = (name, Tree t)
-  | dest_binding b = raise SMTLIB2_PARSE ("bad SMT let binding format", b)
-
-fun term_of t cx =
-  (case t of
-    SMTLIB2.S [SMTLIB2.Sym "forall", SMTLIB2.S vars, body] => quant HOLogic.mk_all vars body cx
-  | SMTLIB2.S [SMTLIB2.Sym "exists", SMTLIB2.S vars, body] => quant HOLogic.mk_exists vars body cx
-  | SMTLIB2.S [SMTLIB2.Sym "let", SMTLIB2.S bindings, body] =>
-      with_bindings (map dest_binding bindings) (term_of body) cx
-  | SMTLIB2.S (SMTLIB2.Sym "!" :: t :: _) => term_of t cx
-  | SMTLIB2.S (f :: args) =>
-      cx
-      |> fold_map term_of args
-      |-> parse_term f
-  | SMTLIB2.Sym name =>
-      (case lookup_binding cx name of
-        Tree u =>
-          cx
-          |> term_of u
-          |-> (fn u' => pair u' o update_binding (name, Term u'))
-      | Term u => (u, cx)
-      | None => parse_term t [] cx
-      | _ => raise SMTLIB2_PARSE ("bad SMT term format", t))
-  | _ => parse_term t [] cx)
-
-and quant q vars body cx =
-  let val vs = map (dest_var cx) vars
-  in
-    cx
-    |> with_bindings (map (apsnd (Term o Free)) vs) (term_of (dest_body body))
-    |>> fold_rev (fn (_, (n, T)) => fn t => q (n, T, t)) vs
-  end
-
-end;