signature CASIFY = sig datatype options = Options of { simp_all_cases: bool, split_right_only: bool,
protect_subgoals: bool }
val hyp_subst_tac: Proof.context -> int -> tactic val SPLIT_subst_tac: Proof.context -> int -> tactic val extract_cases_tac: context_tactic val prepare_labels_tac: Proof.context -> int -> tactic val split_bind_all_tac: {right_only: bool, simp_all_cases: bool} -> Proof.context -> int -> tactic val casify_tac: options -> context_tactic val casify_options: options -> options parser val casify_method_setup: options -> (Proof.context -> Method.method) context_parser end
structure Casify : CASIFY = struct
val bind_unnamedN = "case" val case_premsN = "prems" val case_unnamedN = "unnamed"
datatype'a prg_ctxt = Block of (string * 'a list) datatype'a prg_concl = Prg_Concl of ((string * 'a) option * term)
fun dest_var (Const (@{const_name Case_Labeling.VAR}, _) $ t) = Util.dest_tuple t
| dest_var t = raise TERM ("dest_var", [t])
val dest_vars = HOLogic.dest_list #> maps dest_var
val dest_ct = let fun mk_block na ic vs = letval (_, idx) = HOLogic.dest_number ic in (idx, Block (HOLogic.dest_string na, dest_vars vs)) end
fun dest_block (Const (@{const_name Pair}, _) $ na $ (Const (@{const_name Pair}, _) $ ic $ vs)) =
mk_block na ic vs
| dest_block t = raise TERM ("dest_block", [t]) in HOLogic.dest_list #> rev #> map dest_block end
fun dest_VC (Const (@{const_name Case_Labeling.VC}, _) $ ct $ t) = (dest_ct ct, t)
| dest_VC t = ([], t)
fun try_dest_Trueprop t = casetry HOLogic.dest_Trueprop t of
NONE => t
| SOME t' => t'
fun dest_BIND (Const (@{const_name Case_Labeling.BIND}, _) $ na $ ic $ t) = let val s = HOLogic.dest_string na val (_, n) = HOLogic.dest_number ic in (SOME (s,n), t) end
| dest_BIND t = (NONE, t)
fun dest_SPLIT (Const (@{const_name Case_Labeling.SPLIT}, _) $ t $ u) = (t,u)
| dest_SPLIT t = raise TERM ("dest_SPLIT", [t])
fun dest_Bound (Bound i) = [i]
| dest_Bound t = raise TERM ("dest_bound", [t])
fun parse_label prop = let val vars = Term.strip_all_vars prop val ((prems, label), _) = prop
|> (Logic.strip_horn o Term.strip_all_body)
||> try_dest_Trueprop
||>> dest_VC in { vars=vars, label=label, prems=prems} end
fun parse_prem prop = let val vars = Term.strip_all_vars prop val (prems, (hier, concl)) = prop
|> (Logic.strip_horn o Term.strip_all_body)
||> try_dest_Trueprop
||> dest_HIER val prop' = Logic.list_all (vars, Logic.list_implies (prems, HOLogic.mk_Trueprop concl)) in (hier, prop') end
fun strip_prg_ctxt n ((params, t), _) = let fun lookup_delete eq y = let fun aux _ [] = error ("Term is not a parameter: " ^ @{make_string} y)
| aux acc ((k,v) :: xs) = if eq (k, y) then (v, rev acc @ xs) else aux ((k,v) :: acc) xs in aux [] end
fun upd_label_vars ps [] = [(~n, Block (case_unnamedN, map snd ps))]
| upd_label_vars ps [(n, Block (s,vs))] = let val (vs', ps') = fold_map (lookup_delete (op aconv)) vs ps in [(n, Block (s, vs' @ map snd ps'))] end
| upd_label_vars ps ((n, Block (s,vs)) :: ct) = letval (vs', ps') = fold_map (lookup_delete (op aconv)) vs ps in (n, Block (s,vs')) :: upd_label_vars ps' ct end
val (asms, (label, concl)) = t
|> Logic.strip_horn
||> try_dest_Trueprop
||> dest_VC
val prg_ctxt = upd_label_vars (build_param_map params) label
val ctxt_len = length prg_ctxt val asms' = map (parse_prem #> apfst (the_default ctxt_len)) asms in
(prg_ctxt, (asms', concl)) end
fun strip_prg_ctxts xs = letval n = length xs in map_index (fn (i,x) => strip_prg_ctxt (n - i) x) xs end
datatype ('a,'b) precase = Precase of
{fixes: (binding * typ) list,
assumes: ('b * term list) list,
binds: (indexname * term option) list,
cases: ('a * ('a,'b) precase) list}
fun bindings args = map (apfst Binding.name) args
fun coalesce_order ord = sort (Util.fst_ord ord) #> AList.coalesce (is_equal o ord)
fun unique_names xs = fst (fold_map (Util.infst Name.variant) xs Name.context)
fun build_precase (prg_ctxt, (prems, t))= let val sorted_prems = prems
|> map (apsnd (fn t => (fst (dest_BIND (try_dest_Trueprop t)), t)))
|> sort (prod_ord int_ord (prod_ord (option_ord (prod_ord fast_string_ord int_ord)) (K EQUAL)))
fun drop_labels (Const (@{const_name "Case_Labeling.BIND"}, _) $ _ $ _ $ t ) = drop_labels t
| drop_labels (t1 $ t2) = drop_labels t1 $ drop_labels t2
| drop_labels (Abs (x,T,t)) = Abs (x,T, drop_labels t)
| drop_labels t = t
(* XXX integrate with drop_labels, to save a second pass *) fun find_binds (t as Const (@{const_name "Case_Labeling.BIND"}, _) $ _ $ _ $ _) =
( case dest_BIND t of
(NONE, t) => find_binds t
| (SOME (s,n), t) => (n,(s,t)) :: find_binds t)
| find_binds (t1 $ t2) = find_binds t1 @ find_binds t2
| find_binds (Abs (_,_,t)) = find_binds t
| find_binds _ = []
fun has_loose_bounds t = case loose_bnos t of
[] => false
| _ :: _ => (warning "loose bounds in term"; true) (*XXX*)
fun unique_binds _ [] = []
| unique_binds acc ((s,x) :: xs) =
(case AList.lookup (op=) acc s of
NONE => ((s,0), x) :: unique_binds ((s,0) :: acc) xs
| SOME n => ((s,n+1), x) :: unique_binds (AList.update (op=) (s,n+1) acc) xs
)
fun mk_precase _ _ [] [] = []
| mk_precase _ _ [] (_::_) = error "premise with a too long HIERarchy label"
| mk_precase n abs_ofixes (bl :: prg_ctxt) prems = let val (m, Block (s, vars)) = bl val fixes = map #fix vars val params = map #abs vars val (prems1, prems2) = chop_prefix (fn (m,_) => m = n) prems
val abs_fixes = abs_ofixes o fold_rev Term.absfree params
val lvars = bv_ts @ sv_ts
|> maps dest_Bound
|> sort_distinct int_ord
|> map (fn n => nvars - n - 1) in Conv.every_conv (map (split_nth_all_conv right_only ctxt) lvars) ct end
fun RAWCONV cv i st = Seq.single (Conv.gconv_rule cv i st)
fun split_bind_all_tac {right_only: bool, simp_all_cases: bool} ctxt = let val rewr_tac = if simp_all_cases then Simplifier.rewrite_goal_tac ctxt [case_prod_th] else K all_tac in
RAWCONV (split_bind_all_conv {right_only = right_only} ctxt) THEN' rewr_tac end
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 und die Messung sind noch experimentell.