scyther-proof-0.3.0: data/isabelle/src/ESPLogic/espl_utils.ML
(*****************************************************************************
* ESPL --- an embedded security protocol logic
* http://people.inf.ethz.ch/meiersi/espl/
*
* Copyright (c) 2009-2011, Simon Meier, ETH Zurich, Switzerland
*
* All rights reserved. See file LICENCE for more information.
******************************************************************************)
(* Various utility functions for working with Pure, HOL, and ESPL related terms. *)
signature ESPL_UTILS =
sig
(* ML specific functions *)
val choose2: 'a list -> ('a * 'a) list
val unique_numbers: int -> ('a * 'a -> bool) -> 'a list -> ('a * int) list
val optional_numbers: ('a * 'a -> bool) -> 'a list -> ('a * int option) list
val blank_zero_numbers: ('a * 'a -> bool) -> 'a list -> ('a * int option) list
val append_optional_number: string -> string * int option -> string
(* Pure specific functions *)
val local_standard': thm -> thm
val expand_term: simpset -> term -> thm
val thms_to_simpset: Proof.context -> thm list -> simpset
val prove_prop
: Proof.context -> ({prems: thm list, context: Proof.context} -> tactic) -> term -> thm
val notes_expansion
: simpset -> (Attrib.binding * (term list * Args.src list) list) list ->
local_theory -> (string * thm list) list * local_theory
val note_expansion
: simpset -> Attrib.binding * term list ->
local_theory -> (string * thm list) * local_theory
val notes_proven
: ({prems: thm list, context: Proof.context} -> tactic) ->
(Attrib.binding * (term list * Args.src list) list) list ->
Proof.context -> (string * thm list) list * local_theory
val note_proven
: ({prems: thm list, context: Proof.context} -> tactic) ->
Attrib.binding * term list ->
Proof.context -> (string * thm list) * local_theory
val add_simple_locale
: binding -> xstring -> term option list -> theory -> string * local_theory
val add_simple_locale_cmd
: binding ->
xstring -> term option list -> Toplevel.transition -> Toplevel.transition
(* HOL specific functions *)
val gather_props: (term -> 'a) -> term list -> 'a list
val dest_HOL_def: term -> term * term
val symmetric_HOL_def: thm -> thm
val prove_distinctness:
Proof.context -> ({prems: thm list, context: Proof.context} -> tactic) -> term list -> thm list
val att_iff_add: Args.src
val att_simp_add: Args.src
end;
structure ESPL_Utils: ESPL_UTILS =
struct
(******************************************************************************
** ML specific functions
******************************************************************************)
(* all possibilities to choose two elements out of a list *)
fun choose2 [] = []
| choose2 (x::xs) = map (pair x) xs @ choose2 xs
(* adds numbers to a list of possibly dupliate names such that each of the
duplicate name gets its own number.
*)
fun unique_numbers start eq (names : 'a list) =
let fun add_number (numbered, name) =
case AList.lookup eq numbered name of
SOME i =>
((name, i+1) :: numbered)
| NONE =>
((name, start) :: numbered)
in rev (Library.foldl add_number ([],names)) end;
(* like unique numbers but doesn't assign a number to non-duplicate names *)
fun optional_numbers eq =
let
fun mk_optional [] = []
| mk_optional ((n,i)::xs) =
(n, if (i > 1) orelse (exists (curry eq n o fst) xs) then SOME i else NONE)
:: mk_optional xs
in mk_optional o unique_numbers 1 eq end;
(* like unique numbers, but blanks out the first occurrences of an element*)
fun blank_zero_numbers eq =
let fun blank (n,i) = if (equal i 0) then (n,NONE) else (n,SOME i)
in map blank o unique_numbers 0 eq end;
(* appends an optional number using the given separator *)
fun append_optional_number _ (n,NONE) = n
| append_optional_number sep (n,SOME i) = n ^ sep ^ string_of_int i
(******************************************************************************
** Pure specific functions
******************************************************************************)
(* An adaption of Drule.standard' such that hypotheses are not 'taken down' as
premises
*)
val local_standard' =
forall_intr_frees
#> `Thm.maxidx_of
#-> (fn maxidx =>
Thm.forall_elim_vars (maxidx + 1)
#> Thm.strip_shyps
#> zero_var_indexes
#> Thm.varifyT);
(* Generate the theorem proving the expansion of a term wrto to the given
simpset and convert it into a rule.
*)
fun expand_term ss t = t
|> Thm.cterm_of (ProofContext.theory_of (MetaSimplifier.the_context ss))
|> Simplifier.rewrite ss
|> (fn conv => conv RS @{thm meta_eq_to_obj_eq})
|> local_standard'
(* Prove the validity of a proposition with a given tactic. *)
fun prove_prop ctxt mk_tactic goal = Goal.prove ctxt [] [] goal mk_tactic;
(* create a simpset consisting only of the given theorems in the given context *)
fun thms_to_simpset ctxt ths =
Simplifier.context ctxt (MetaSimplifier.empty_ss addsimps ths);
(* Expand a list of terms and note the resulting theorems. *)
fun notes_expansion ss to_expand =
Local_Theory.notes (map (apsnd (map (apfst (map (expand_term ss))))) to_expand);
(* Expand a term and note the resulting theorem. *)
fun note_expansion ss (a, ts) =
notes_expansion ss [(a, [(ts, [])])] #>> the_single;
(* Prove a list of propositions and note the resulting theorems *)
fun notes_proven mk_tactic to_prove ctxt =
Local_Theory.notes
(map (apsnd (map (apfst (map (prove_prop ctxt mk_tactic))))) to_prove)
ctxt;
(* Prove a proposition and note the resulting theorem *)
fun note_proven mk_tactic (a, ts) =
notes_proven mk_tactic [(a, [(ts, [])])] #>> the_single;
(* A simplified version of the Expression.add_locale command for
emulating the Isar script "locale b = loc_name inst" where
inst is a positional instantiation.
*)
fun add_simple_locale b loc_name inst thy =
Expression.add_locale b (Binding.empty)
( [ ( Locale.intern thy loc_name
, ( ("",false)
, Expression.Positional inst
)
)
]
, [] )
[]
thy;
fun add_simple_locale_cmd b loc_name inst =
Toplevel.begin_local_theory false (#2 o add_simple_locale b loc_name inst);
(******************************************************************************
** HOL specific functions
******************************************************************************)
(* Gathers proposition destructible using the given destructor *)
fun gather_props dest = map_filter (try (dest o HOLogic.dest_Trueprop))
(* destruct a HOL definition; i.e. either "lhs == rhs" or "lhs = rhs" *)
fun dest_HOL_def t =
(t |> HOLogic.dest_Trueprop |> HOLogic.dest_eq)
handle TERM _ => Logic.dest_equals t
(* returns the symmetric variant of a Pure or HOL equality *)
fun symmetric_HOL_def th =
Thm.symmetric th
handle THM ("symmetric", _, _) => th RS sym |> Drule.zero_var_indexes
(* Proves the distinctness of all non-reflexive pairs of the list of terms
using the given tactic.
*)
fun prove_distinctness ctxt mk_tactic ts =
let fun mk_ineqs (t1,t2) =
let val th = prove_prop ctxt mk_tactic
(HOLogic.mk_Trueprop (HOLogic.mk_not( HOLogic.mk_eq (t1,t2))))
in [th, th RS @{thm not_sym}] end
in flat (map mk_ineqs (choose2 ts)) end
(* shorthands for common attributes *)
val att_iff_add = Attrib.internal (K Clasimp.iff_add)
val att_simp_add = Attrib.internal (K Simplifier.simp_add)
end;