(* ========================================================================= *) (* Isabelle Light *) (* Isabelle/Procedural style additions and other user-friendly shortcuts. *) (* *) (* Petros Papapanagiotou, Jacques Fleuriot *) (* Center of Intelligent Systems and their Applications *) (* University of Edinburgh *) (* 2009-2012 *) (* ========================================================================= *) (* FILE : support.ml *) (* DESCRIPTION : Support functions and various shortcuts. *) (* LAST MODIFIED: October 2012 *) (* ========================================================================= *) (* ------------------------------------------------------------------------- *) (* Functions to deal with triplets: *) (* ------------------------------------------------------------------------- *) let fst3 (x,_,_) = x;; let snd3 (_,x,_) = x;; let thd3 (_,_,x) = x;; (*----------------------------------------------------------------------------*) (* num_list : a' list -> (a' * int) list *) (* *) (* Numbers a list of elements, *) (* e.g. [`a`;`b`;`c`] ---> [(0,`a`);(1,`b`);(2,`c`)]. *) (*----------------------------------------------------------------------------*) let num_list l = let rec number_list' n l = if ( l = [] ) then [] else (n,hd l)::(number_list' (n + 1) (tl l)) in number_list' 0 l;; (* ------------------------------------------------------------------------- *) (* list_match_first: (a' -> b') -> a' list -> b' *) (* Tries to apply a function to the members of a list. Returns the result *) (* from the first member that succeeds. *) (* ------------------------------------------------------------------------- *) let rec list_match_first f alist = if (alist = []) then failwith "list_match_first: No matches!" else try f (hd alist) with Failure _ -> list_match_first f (tl alist);; (* ------------------------------------------------------------------------- *) (* terms_match: term list -> term -> term list -> instantiation *) (* Tries to apply term_match to the first possible term in a list. *) (* Returns the insantiation. *) (* ------------------------------------------------------------------------- *) let (terms_match: term list -> term -> term list -> instantiation ) = fun consts key tlist -> try (list_match_first (term_match consts key) tlist) with Failure _ -> failwith "terms_match: No terms match!";; (* ------------------------------------------------------------------------- *) (* thm_mk_primed_vars: term list -> thm -> thm *) (* Renames all free variables in a theorem to avoid specified and constant *) (* names. *) (* ------------------------------------------------------------------------- *) let thm_mk_primed_vars avoids thm = let fvars = thm_frees thm in let new_vars = map (mk_primed_var avoids) fvars in let insts = List.combine new_vars fvars in INST insts thm;; (* ------------------------------------------------------------------------- *) (* gl_frees: goal -> term list *) (* Finds the free variables in a subgoal (assumptions and goal). *) (* ------------------------------------------------------------------------- *) let gl_frees : goal -> term list = fun (asl,w) -> itlist (union o thm_frees o snd) asl (frees w);; (* ------------------------------------------------------------------------- *) (* ADD_HYP: thm -> thm -> thm *) (* Trivially adds the hypotheses of a theorem to the premises of another. *) (* ------------------------------------------------------------------------- *) (* (+) Used in the justification of erule and drule to add the eliminated *) (* assumption to the proven subgoals. *) (* (+) Could have been based on ADD_ASSUM but it's more convenient this way. *) (* ------------------------------------------------------------------------- *) let ADD_HYP hyp_thm thm = CONJUNCT2 (CONJ hyp_thm thm);; (* ------------------------------------------------------------------------- *) (* DISCHL: term list -> thm -> thm *) (* Applies DISCH for several terms. *) (* ------------------------------------------------------------------------- *) let rec (DISCHL: term list -> thm -> thm) = fun tms thm -> if (tms = []) then thm else DISCH (hd tms) (DISCHL (tl tms) thm);; (* ------------------------------------------------------------------------- *) (* print_thl: *) (* Print a list of theorems (for debugging). *) (* ------------------------------------------------------------------------- *) let print_thl thl = map (fun thm -> ( print_thm thm ; print_newline ())) thl;; (* ------------------------------------------------------------------------- *) (* print_tml: *) (* Print a list of terms (for debugging). *) (* ------------------------------------------------------------------------- *) let print_tml tml = map (fun tm -> ( print_term tm ; print_newline ())) tml;; (* ------------------------------------------------------------------------- *) (* print_varandtype, show_types, hide_types: *) (* Prints the type after each variable. Useful for "debugging" type issues. *) (* ------------------------------------------------------------------------- *) (* Source: *) (* http://code.google.com/p/flyspeck/wiki/TipsAndTricks#Investigating_Types *) (* ------------------------------------------------------------------------- *) let print_varandtype tm = let fmt = std_formatter in let hop,args = strip_comb tm in let s = name_of hop and ty = type_of hop in if is_var hop & args = [] then (pp_print_string fmt "("; pp_print_string fmt s; pp_print_string fmt ":"; pp_print_type fmt ty; pp_print_string fmt ")") else fail() ;; let show_types,hide_types = (fun () -> install_user_printer ("Show Types",print_varandtype)), (fun () -> try delete_user_printer "Show Types" with Failure _ -> failwith ("hide_types: "^ "Types are already hidden."));; (* ------------------------------------------------------------------------- *) (* count_goals : unit -> int *) (* Shortcut to count the subgoals in the current goalstate. *) (* ------------------------------------------------------------------------- *) let count_goals () = if (!current_goalstack = []) then 0 else ( let _,gls,_ = hd !current_goalstack in length gls );; (* ------------------------------------------------------------------------- *) (* top_asms : goalstack -> (string * thm) list *) (* Shortcut to get the assumption list of the top goal of a given goalstack. *) (* ------------------------------------------------------------------------- *) let top_asms (gs:goalstack) = (fst o hd o snd3 o hd) gs;; (* ------------------------------------------------------------------------- *) (* top_metas : goalstack -> term list *) (* Returns the list of metavariables in the current goalstate. *) (* ------------------------------------------------------------------------- *) let top_metas (gs:goalstack) = (fst o fst3 o hd) gs;; (* ------------------------------------------------------------------------- *) (* top_inst : goalstack -> instantiation *) (* Returns the metavariable instantiations in the current goalstate. *) (* ------------------------------------------------------------------------- *) let top_inst (gs:goalstack) = (snd o fst3 o hd) gs;; (* ------------------------------------------------------------------------- *) (* print_goalstack_all : *) (* Alternative goalstack printer that always prints all subgoals. *) (* Also prints list of metavariables with their types. *) (* ------------------------------------------------------------------------- *) (* Original printer only prints more than one subgoals iff they were *) (* generated by the last step. Otherwise it only prints the 'active' subgoal.*) (* Replace by #install_printer print_goalstack_all;; *) (* Revert to original by #install_printer print_goalstack;; *) (* ------------------------------------------------------------------------- *) let (print_goalstack_all:goalstack->unit) = let print_goalstate k gs = let ((mvs,_),gl,_) = gs in let n = length gl in let s = if n = 0 then "No subgoals" else (string_of_int k)^" subgoal"^(if k > 1 then "s" else "") ^" ("^(string_of_int n)^" total)" in let print_mv v = print_string " `" ; print_varandtype v ; print_string "`;" in print_string s; print_newline(); if (length mvs > 0) then ( print_string "Metas:" ; let _ = map print_mv mvs in () ; print_newline() ) ; if gl = [] then () else do_list (print_goal o C el gl) (rev(0--(k-1))) in fun l -> if l = [] then print_string "Empty goalstack" else let (_,gl,_ as gs) = hd l in print_goalstate (length gl) gs;; (* ------------------------------------------------------------------------- *) (* print_goalstack : *) (* Upgrade to print_goalstack that also prints a list of metavariables with *) (* their types. *) (* ------------------------------------------------------------------------- *) let (print_goalstack:goalstack->unit) = let print_goalstate k gs = let ((mvs,_),gl,_) = gs in let n = length gl in let s = if n = 0 then "No subgoals" else (string_of_int k)^" subgoal"^(if k > 1 then "s" else "") ^" ("^(string_of_int n)^" total)" in let print_mv v = print_string " `" ; print_varandtype v ; print_string "`;" in print_string s; print_newline(); if (length mvs > 0) then ( print_string "Metas:" ; let _ = map print_mv mvs in () ; print_newline() ) ; if gl = [] then () else do_list (print_goal o C el gl) (rev(0--(k-1))) in fun l -> if l = [] then print_string "Empty goalstack" else if tl l = [] then let (_,gl,_ as gs) = hd l in print_goalstate 1 gs else let (_,gl,_ as gs) = hd l and (_,gl0,_) = hd(tl l) in let p = length gl - length gl0 in let p' = if p < 1 then 1 else p + 1 in print_goalstate p' gs;; #install_printer print_goalstack;;