5 Visualize dependencies of theorems. |
5 Visualize dependencies of theorems. |
6 *) |
6 *) |
7 |
7 |
8 signature THM_DEPS = |
8 signature THM_DEPS = |
9 sig |
9 sig |
10 val enable: unit -> unit |
|
11 val disable: unit -> unit |
|
12 val thm_deps: thm list -> unit |
10 val thm_deps: thm list -> unit |
13 val unused_thms: theory list * theory list -> (string * thm) list |
11 val unused_thms: theory list * theory list -> (string * thm) list |
14 end; |
12 end; |
15 |
13 |
16 structure ThmDeps: THM_DEPS = |
14 structure ThmDeps: THM_DEPS = |
17 struct |
15 struct |
18 |
16 |
19 (* thm_deps *) |
17 (* thm_deps *) |
20 |
18 |
21 fun enable () = CRITICAL (fn () => if ! proofs = 0 then proofs := 1 else ()); |
19 fun add_dep ((name, _, _), PBody {thms = thms', ...}) = |
22 fun disable () = proofs := 0; |
20 name <> "" ? |
23 |
21 Graph.new_node (name, ()) #> |
24 local |
22 fold (fn (_, ((name', _, _), _)) => name <> "" ? Graph.add_edge (name', name)) thms'; |
25 |
|
26 open Proofterm; |
|
27 |
|
28 fun dest_thm_axm (PThm (name, prf, _, _)) = (name, prf) |
|
29 | dest_thm_axm (PAxm (name, _, _)) = (name ^ " (Ax)", MinProof ([], [], [])) |
|
30 | dest_thm_axm _ = ("", MinProof ([], [], [])); |
|
31 |
|
32 fun make_deps_graph (AbsP (_, _, prf)) = make_deps_graph prf |
|
33 | make_deps_graph (Abst (_, _, prf)) = make_deps_graph prf |
|
34 | make_deps_graph (prf1 %% prf2) = make_deps_graph prf1 #> make_deps_graph prf2 |
|
35 | make_deps_graph (prf % _) = make_deps_graph prf |
|
36 | make_deps_graph (MinProof (thms, axms, _)) = |
|
37 fold (make_deps_graph o Proofterm.proof_of_min_thm) thms #> |
|
38 fold (make_deps_graph o Proofterm.proof_of_min_axm) axms |
|
39 | make_deps_graph prf = (fn p as (gra, parents) => |
|
40 let val (name, prf') = dest_thm_axm prf |
|
41 in |
|
42 if name <> "" then |
|
43 if not (Symtab.defined gra name) then |
|
44 let |
|
45 val (gra', parents') = make_deps_graph prf' (gra, []); |
|
46 val prefx = #1 (Library.split_last (NameSpace.explode name)); |
|
47 val session = |
|
48 (case prefx of |
|
49 (x :: _) => |
|
50 (case ThyInfo.lookup_theory x of |
|
51 SOME thy => |
|
52 let val name = Present.session_name thy |
|
53 in if name = "" then [] else [name] end |
|
54 | NONE => []) |
|
55 | _ => ["global"]); |
|
56 in |
|
57 if member (op =) parents' name then (gra', parents union parents') |
|
58 else (Symtab.update (name, |
|
59 {name = Sign.base_name name, ID = name, |
|
60 dir = space_implode "/" (session @ prefx), |
|
61 unfold = false, path = "", parents = parents'}) gra', |
|
62 insert (op =) name parents) |
|
63 end |
|
64 else (gra, insert (op =) name parents) |
|
65 else |
|
66 make_deps_graph prf' (gra, parents) |
|
67 end); |
|
68 |
|
69 in |
|
70 |
23 |
71 fun thm_deps thms = |
24 fun thm_deps thms = |
72 Present.display_graph |
25 let |
73 (map snd (sort_wrt fst (Symtab.dest (fst |
26 val graph = Proofterm.fold_body_thms add_dep (map Thm.proof_of thms) Graph.empty; |
74 (fold make_deps_graph (map Thm.proof_of thms) (Symtab.empty, [])))))); |
27 fun add_entry (name, (_, (preds, _))) = |
75 |
28 let |
76 end; |
29 val prefix = #1 (Library.split_last (NameSpace.explode name)); |
|
30 val session = |
|
31 (case prefix of |
|
32 a :: _ => |
|
33 (case ThyInfo.lookup_theory a of |
|
34 SOME thy => |
|
35 (case Present.session_name thy of |
|
36 "" => [] |
|
37 | session => [session]) |
|
38 | NONE => []) |
|
39 | _ => ["global"]); |
|
40 val entry = |
|
41 {name = Sign.base_name name, |
|
42 ID = name, |
|
43 dir = space_implode "/" (session @ prefix), |
|
44 unfold = false, |
|
45 path = "", |
|
46 parents = preds}; |
|
47 in cons entry end; |
|
48 in Present.display_graph (sort_wrt #ID (Graph.fold add_entry graph [])) end; |
77 |
49 |
78 |
50 |
79 (* unused_thms *) |
51 (* unused_thms *) |
80 |
52 |
81 fun unused_thms (base_thys, thys) = |
53 fun unused_thms (base_thys, thys) = |
84 if exists (fn thy => PureThy.defined_fact thy name) base_thys then I |
56 if exists (fn thy => PureThy.defined_fact thy name) base_thys then I |
85 else fold_rev (fn th => (case Thm.get_name th of "" => I | a => cons (a, th))) ths; |
57 else fold_rev (fn th => (case Thm.get_name th of "" => I | a => cons (a, th))) ths; |
86 val thms = |
58 val thms = |
87 fold (Facts.fold_static add_fact o PureThy.facts_of) thys [] |
59 fold (Facts.fold_static add_fact o PureThy.facts_of) thys [] |
88 |> sort_distinct (string_ord o pairself #1); |
60 |> sort_distinct (string_ord o pairself #1); |
89 val tab = fold Proofterm.thms_of_proof |
61 |
|
62 val tab = Proofterm.fold_body_thms |
|
63 (fn ((name, prop, _), _) => name <> "" ? Symtab.insert_list (op =) (name, prop)) |
90 (map (Proofterm.strip_thm o Thm.proof_of o snd) thms) Symtab.empty; |
64 (map (Proofterm.strip_thm o Thm.proof_of o snd) thms) Symtab.empty; |
91 fun is_unused (name, th) = case Symtab.lookup tab name of |
65 fun is_unused (name, th) = |
92 NONE => true |
66 not (member (op aconv) (Symtab.lookup_list tab name) (Thm.prop_of th)); |
93 | SOME ps => not (member (op aconv) (map fst ps) (Thm.prop_of th)); |
67 |
94 (* groups containing at least one used theorem *) |
68 (* groups containing at least one used theorem *) |
95 val grps = fold (fn p as (_, thm) => if is_unused p then I else |
69 val grps = fold (fn p as (_, thm) => if is_unused p then I else |
96 case Thm.get_group thm of |
70 case Thm.get_group thm of |
97 NONE => I | SOME grp => Symtab.update (grp, ())) thms Symtab.empty; |
71 NONE => I | SOME grp => Symtab.update (grp, ())) thms Symtab.empty; |
98 val (thms', _) = fold (fn p as (s, thm) => fn q as (thms, grps') => |
72 val (thms', _) = fold (fn p as (s, thm) => fn q as (thms, grps') => |