1 (* Title: Pure/Isar/calculation.ML
3 Author: Markus Wenzel, TU Muenchen
4 License: GPL (GNU GENERAL PUBLIC LICENSE)
6 Support for calculational proofs.
9 signature CALCULATION =
11 val print_global_rules: theory -> unit
12 val print_local_rules: Proof.context -> unit
13 val trans_add_global: theory attribute
14 val trans_del_global: theory attribute
15 val trans_add_local: Proof.context attribute
16 val trans_del_local: Proof.context attribute
17 val also: thm list option -> (thm list -> unit) -> Proof.state -> Proof.state Seq.seq
18 val finally: thm list option -> (thm list -> unit) -> Proof.state -> Proof.state Seq.seq
19 val moreover: (thm list -> unit) -> Proof.state -> Proof.state
20 val ultimately: (thm list -> unit) -> Proof.state -> Proof.state
21 val setup: (theory -> theory) list
24 structure Calculation: CALCULATION =
27 (** global and local calculation data **)
29 (* theory data kind 'Isar/calculation' *)
31 fun print_rules rs = Pretty.writeln (Pretty.big_list "calculation rules:"
32 (map Display.pretty_thm (NetRules.rules rs)));
34 structure GlobalCalculationArgs =
36 val name = "Isar/calculation";
37 type T = thm NetRules.T
39 val empty = NetRules.init_elim;
42 val merge = NetRules.merge;
43 fun print _ = print_rules;
46 structure GlobalCalculation = TheoryDataFun(GlobalCalculationArgs);
47 val print_global_rules = GlobalCalculation.print;
50 (* proof data kind 'Isar/calculation' *)
52 structure LocalCalculationArgs =
54 val name = "Isar/calculation";
55 type T = thm NetRules.T * (thm list * int) option;
57 fun init thy = (GlobalCalculation.get thy, None);
58 fun print _ (rs, _) = print_rules rs;
61 structure LocalCalculation = ProofDataFun(LocalCalculationArgs);
62 val get_local_rules = #1 o LocalCalculation.get_st;
63 val print_local_rules = LocalCalculation.print;
66 (* access calculation *)
68 fun get_calculation state =
69 (case #2 (LocalCalculation.get_st state) of
71 | Some (thms, lev) => if lev = Proof.level state then Some thms else None);
73 fun put_calculation thms state =
74 LocalCalculation.put_st (get_local_rules state, Some (thms, Proof.level state)) state;
76 fun reset_calculation state =
77 LocalCalculation.put_st (get_local_rules state, None) state;
85 fun mk_att f g (x, thm) = (f (g thm) x, thm);
87 val trans_add_global = mk_att GlobalCalculation.map NetRules.insert;
88 val trans_del_global = mk_att GlobalCalculation.map NetRules.delete;
89 val trans_add_local = mk_att LocalCalculation.map (Library.apfst o NetRules.insert);
90 val trans_del_local = mk_att LocalCalculation.map (Library.apfst o NetRules.delete);
96 (Attrib.add_del_args trans_add_global trans_del_global,
97 Attrib.add_del_args trans_add_local trans_del_local);
101 (** proof commands **)
103 (* maintain calculation register *)
105 val calculationN = "calculation";
107 fun maintain_calculation false calc state =
109 |> put_calculation calc
110 |> Proof.simple_have_thms calculationN calc
112 | maintain_calculation true calc state =
115 |> Proof.reset_thms calculationN
116 |> Proof.simple_have_thms "" calc
120 (* 'also' and 'finally' *)
122 fun err_if state b msg = if b then raise Proof.STATE (msg, state) else ();
124 fun calculate final opt_rules print state =
126 val facts = Proof.the_facts state;
128 val eq_prop = op aconv o pairself (Pattern.eta_contract o #prop o Thm.rep_thm);
129 fun differ thms thms' = not (Library.equal_lists eq_prop (thms, thms'));
133 val ths = thms @ facts;
134 val rs = get_local_rules state;
136 (case ths of [] => NetRules.rules rs
137 | th :: _ => NetRules.may_unify rs (Logic.strip_assums_concl (#prop (Thm.rep_thm th))));
138 val ruleq = Seq.of_list (if_none opt_rules [] @ rules);
139 in Seq.map Library.single (Seq.flat (Seq.map (Method.multi_resolve ths) ruleq)) end;
141 val (initial, calculations) =
142 (case get_calculation state of
143 None => (true, Seq.single facts)
144 | Some thms => (false, Seq.filter (differ thms) (combine thms)))
146 err_if state (initial andalso final) "No calculation yet";
147 err_if state (initial andalso is_some opt_rules) "Initial calculation -- no rules to be given";
148 calculations |> Seq.map (fn calc => (print calc; state |> maintain_calculation final calc))
151 fun also print = calculate false print;
152 fun finally print = calculate true print;
155 (* 'moreover' and 'ultimately' *)
157 fun collect final print state =
159 val facts = Proof.the_facts state;
160 val (initial, thms) =
161 (case get_calculation state of
163 | Some thms => (false, thms));
164 val calc = thms @ facts;
166 err_if state (initial andalso final) "No calculation yet";
168 state |> maintain_calculation final calc
171 fun moreover print = collect false print;
172 fun ultimately print = collect true print;
178 val setup = [GlobalCalculation.init, LocalCalculation.init,
179 Attrib.add_attributes [("trans", trans_attr, "declare transitivity rule")]];