walther@59866
|
1 |
(* Title: BaseDefinitions/thmC.sml
|
walther@59865
|
2 |
Author: Walther Neuper
|
walther@59865
|
3 |
(c) due to copyright terms
|
walther@59865
|
4 |
|
walther@59876
|
5 |
This structure could be dropped due to improved reflection in Isabelle;
|
walther@59876
|
6 |
but ThmC.sym_thm requires still an identifying string thm_id.
|
walther@59865
|
7 |
*)
|
walther@59865
|
8 |
signature THEOREM_ISAC =
|
walther@59865
|
9 |
sig
|
walther@59874
|
10 |
type T = ThmC_Def.T
|
walther@59914
|
11 |
type id = ThmC_Def.id (* shortest possible *)
|
walther@59914
|
12 |
type long_id (* e.g. "Test.radd_left_commute"*)
|
walther@59914
|
13 |
|
walther@59915
|
14 |
val cut_id: string -> id
|
walther@59914
|
15 |
val long_id: T -> long_id
|
Walther@60592
|
16 |
|
walther@59876
|
17 |
val string_of_thm: thm -> string
|
walther@59876
|
18 |
val string_of_thms: thm list -> string
|
Walther@60592
|
19 |
(*stepwise replace ^^^ by vvv and finally rename by eliminating "_PIDE"*)
|
Walther@60592
|
20 |
(*val string_of:*)
|
Walther@60592
|
21 |
val string_of_thm_PIDE: Proof.context -> thm -> string
|
Walther@60592
|
22 |
val string_of_thms_PIDE: Proof.context -> thm list -> string
|
Walther@60592
|
23 |
|
walther@59914
|
24 |
val id_of_thm: thm -> id
|
walther@59876
|
25 |
val of_thm: thm -> T
|
Walther@60644
|
26 |
val from_rule : Proof.context -> Rule.rule -> T
|
walther@60017
|
27 |
val member': id list -> Rule.rule -> bool
|
walther@59915
|
28 |
|
walther@59876
|
29 |
val is_sym: id -> bool
|
walther@60370
|
30 |
val thm_from_thy: theory -> id -> thm
|
walther@59915
|
31 |
|
wenzelm@60296
|
32 |
val make_rule: Proof.context -> bool -> string * Position.T -> Rule_Def.rule
|
wenzelm@60296
|
33 |
|
wenzelm@60223
|
34 |
\<^isac_test>\<open>
|
walther@60220
|
35 |
val dest_eq_concl: thm -> term * term
|
walther@59876
|
36 |
val string_of_thm_in_thy: theory -> thm -> string
|
walther@59876
|
37 |
val id_drop_sym: id -> id
|
Walther@60644
|
38 |
val revert_sym_rule: theory -> Rule.rule -> Rule.rule
|
wenzelm@60223
|
39 |
\<close>
|
Walther@60644
|
40 |
val make_sym_rule: Proof.context -> Rule.rule -> Rule.rule
|
walther@59876
|
41 |
val make_sym_rule_set: Rule_Set.T -> Rule_Set.T
|
walther@59876
|
42 |
val sym_thm: thm -> thm
|
walther@59865
|
43 |
end
|
walther@59865
|
44 |
|
walther@59865
|
45 |
(**)
|
walther@59865
|
46 |
structure ThmC(**): THEOREM_ISAC(**) =
|
walther@59865
|
47 |
struct
|
walther@59865
|
48 |
(**)
|
walther@59865
|
49 |
|
walther@59915
|
50 |
(** types and conversions **)
|
walther@59915
|
51 |
|
walther@59874
|
52 |
type T = ThmC_Def.T;
|
walther@59874
|
53 |
type id = ThmC_Def.id;
|
walther@59914
|
54 |
type long_id = string;
|
walther@59871
|
55 |
|
walther@59915
|
56 |
fun long_id (thmID, _) = thmID |> Global_Theory.get_thm (ThyC.Isac ()) |> Thm.get_name_hint
|
walther@59915
|
57 |
fun cut_id dn = last_elem (space_explode "." dn); (*the cut_id is the key into Know_Store*)
|
walther@59915
|
58 |
|
walther@59876
|
59 |
val string_of_thm = ThmC_Def.string_of_thm;
|
walther@59876
|
60 |
val string_of_thms = ThmC_Def.string_of_thms;
|
Walther@60592
|
61 |
val string_of_thm_PIDE = ThmC_Def.string_of_thm_PIDE;
|
Walther@60592
|
62 |
val string_of_thms_PIDE = ThmC_Def.string_of_thms_PIDE;
|
walther@59875
|
63 |
|
walther@59915
|
64 |
fun id_of_thm thm = thm |> Thm.get_name_hint |> cut_id;
|
walther@59876
|
65 |
fun of_thm thm = (id_of_thm thm, thm);
|
Walther@60644
|
66 |
fun from_rule _ (Rule.Thm (id, thm)) = (id, thm)
|
Walther@60644
|
67 |
| from_rule ctxt r =
|
Walther@60647
|
68 |
raise ERROR ("ThmC.from_rule: not defined for " ^ Rule.to_string ctxt r);
|
Walther@60644
|
69 |
|
wenzelm@60223
|
70 |
\<^isac_test>\<open>
|
walther@60360
|
71 |
fun string_of_thm_in_thy thy thm =
|
walther@60360
|
72 |
UnparseC.term_in_ctxt (Proof_Context.init_global thy) (Thm.prop_of thm);
|
wenzelm@60223
|
73 |
\<close>
|
walther@60017
|
74 |
fun member' thmIDs thm = (member op = thmIDs (Rule.thm_id thm))
|
walther@59914
|
75 |
handle ERROR _ => false
|
walther@59914
|
76 |
|
walther@59874
|
77 |
|
walther@59876
|
78 |
(** handle symmetric equalities, generated by deriving input terms **)
|
walther@59876
|
79 |
|
walther@59876
|
80 |
fun is_sym id =
|
walther@59876
|
81 |
case Symbol.explode id of "s" :: "y" :: "m" :: "_" :: _ => true
|
walther@59876
|
82 |
| _ => false;
|
walther@59876
|
83 |
fun id_drop_sym id =
|
walther@59876
|
84 |
case Symbol.explode id of "s" :: "y" :: "m" :: "_" :: id => implode id
|
walther@59876
|
85 |
| _ => id
|
walther@59872
|
86 |
|
walther@59872
|
87 |
(* get the theorem associated with the xstring-identifier;
|
walther@60220
|
88 |
if the identifier starts with "sym_" then swap "lhs = rhs" around "=";
|
walther@59878
|
89 |
in case identifiers starting with "#" come from Eval and
|
walther@59876
|
90 |
get an ad-hoc theorem (containing numerals only) -- rejected here
|
walther@59876
|
91 |
*)
|
walther@59876
|
92 |
fun thm_from_thy thy thmid =
|
walther@59872
|
93 |
case Symbol.explode thmid of
|
walther@59876
|
94 |
"s" :: "y" :: "m" :: "_" :: "#" :: _ =>
|
walther@59876
|
95 |
raise ERROR ("thm_from_thy not impl.for " ^ thmid)
|
walther@59876
|
96 |
| "s" :: "y" :: "m" :: "_" :: id =>
|
walther@60337
|
97 |
((Global_Theory.get_thm thy) (implode id)) RS sym
|
walther@59876
|
98 |
| "#" :: _ =>
|
walther@60220
|
99 |
raise ERROR ("thm_from_thy not impl.for " ^ thmid)
|
walther@59876
|
100 |
| _ =>
|
walther@60337
|
101 |
thmid |> Global_Theory.get_thm thy
|
walther@59872
|
102 |
|
wenzelm@60206
|
103 |
fun dest_eq_concl thm =
|
wenzelm@60206
|
104 |
(case try (HOLogic.dest_eq o HOLogic.dest_Trueprop o Logic.strip_imp_concl o Thm.prop_of) thm of
|
wenzelm@60206
|
105 |
NONE => raise THM ("dest_eq_concl: conclusion needs to be HOL equality", 0, [thm])
|
wenzelm@60206
|
106 |
| SOME eq => eq);
|
wenzelm@60206
|
107 |
|
walther@59872
|
108 |
(* A1==>...==> An ==> (Lhs = Rhs) goes to A1 ==>...==> An ==> (Rhs = Lhs) *)
|
wenzelm@60206
|
109 |
(*NB: careful instantiation avoids shifting of schematic variables*)
|
walther@59872
|
110 |
fun sym_thm thm =
|
wenzelm@60206
|
111 |
let
|
wenzelm@60206
|
112 |
val thy = Thm.theory_of_thm thm;
|
wenzelm@60206
|
113 |
val certT = Thm.global_ctyp_of thy;
|
wenzelm@60206
|
114 |
val cert = Thm.global_cterm_of thy;
|
wenzelm@60206
|
115 |
|
wenzelm@60206
|
116 |
val (lhs, rhs) = dest_eq_concl thm |> apply2 cert;
|
wenzelm@60206
|
117 |
val A = Thm.typ_of_cterm lhs;
|
wenzelm@60206
|
118 |
|
wenzelm@60206
|
119 |
val sym_rule = Thm.lift_rule (Thm.cprop_of thm) @{thm sym};
|
wenzelm@60206
|
120 |
val (t, s) = dest_eq_concl sym_rule;
|
wenzelm@60206
|
121 |
|
wenzelm@60404
|
122 |
val instT = TVars.map (K (K A)) (TVars.build (TVars.add_tvars t));
|
wenzelm@60404
|
123 |
val (t', s') = (t, s) |> apply2 (dest_Var o Term_Subst.instantiate (instT, Vars.empty));
|
wenzelm@60206
|
124 |
|
wenzelm@60404
|
125 |
val cinstT = TVars.map (K certT) instT;
|
wenzelm@60404
|
126 |
val cinst = Vars.make [(s', lhs), (t', rhs)];
|
wenzelm@60222
|
127 |
in
|
wenzelm@60222
|
128 |
thm
|
wenzelm@60222
|
129 |
|> Thm.implies_elim (Thm.instantiate (cinstT, cinst) sym_rule)
|
wenzelm@60222
|
130 |
|> Thm.put_name_hint (Thm.get_name_hint thm)
|
wenzelm@60222
|
131 |
end;
|
walther@59872
|
132 |
|
walther@59876
|
133 |
fun make_sym_rule_set Rule_Set.Empty = Rule_Set.Empty
|
Walther@60586
|
134 |
| make_sym_rule_set (Rule_Def.Repeat {id, program, calc, errpatts, asm_rls, prog_rls, rules, rew_ord, preconds}) =
|
Walther@60586
|
135 |
Rule_Def.Repeat {id = "sym_" ^ id, program = program, calc = calc, errpatts = errpatts, asm_rls = asm_rls, prog_rls = prog_rls,
|
walther@59872
|
136 |
rules = rules, rew_ord = rew_ord, preconds = preconds}
|
Walther@60586
|
137 |
| make_sym_rule_set (Rule_Set.Sequence {id, program, calc, errpatts, asm_rls, prog_rls, rules, rew_ord, preconds}) =
|
Walther@60586
|
138 |
Rule_Set.Sequence {id = "sym_" ^ id, program = program, calc = calc, errpatts = errpatts, asm_rls = asm_rls, prog_rls = prog_rls,
|
walther@59872
|
139 |
rules = rules, rew_ord = rew_ord, preconds = preconds}
|
Walther@60586
|
140 |
| make_sym_rule_set (Rule_Set.Rrls {id, program, calc, errpatts, asm_rls, prepat, rew_ord}) =
|
Walther@60586
|
141 |
Rule_Set.Rrls {id = "sym_" ^ id, program = program, calc = calc, errpatts = errpatts, asm_rls = asm_rls,
|
walther@59872
|
142 |
prepat = prepat, rew_ord = rew_ord}
|
walther@59872
|
143 |
|
walther@59876
|
144 |
(* toggles sym_* and keeps "#:" for ad-hoc theorems *)
|
Walther@60644
|
145 |
fun make_sym_rule ctxt (Rule.Thm (thmID, thm)) =
|
Walther@60630
|
146 |
let
|
Walther@60630
|
147 |
val thm' = sym_thm thm
|
Walther@60630
|
148 |
val thmID' = case Symbol.explode thmID of
|
Walther@60630
|
149 |
"s" :: "y" :: "m" :: "_" :: id => implode id
|
Walther@60630
|
150 |
| "#" :: ":" :: _ => "#: " ^ string_of_thm_PIDE ctxt thm'
|
Walther@60630
|
151 |
| _ => "sym_" ^ thmID
|
Walther@60630
|
152 |
in Rule.Thm (thmID', thm') end
|
Walther@60644
|
153 |
| make_sym_rule _ (Rule.Rls_ rls) = Rule.Rls_ (make_sym_rule_set rls)
|
Walther@60647
|
154 |
| make_sym_rule ctxt r = raise ERROR ("ThmC.make_sym_rule: not for " ^ Rule.to_string ctxt r)
|
walther@59872
|
155 |
|
Walther@60644
|
156 |
\<^isac_test>\<open>
|
walther@60370
|
157 |
(* revert a thm RS @{thm sym} back to original thm, in case it ML\<open>is_sym\<close> *)
|
walther@59876
|
158 |
fun revert_sym_rule thy (Rule.Thm (id, thm)) =
|
walther@60370
|
159 |
(*this ^^ might come from the user, who doesn't care about thy*)
|
walther@59876
|
160 |
if is_sym (cut_id id)
|
walther@59874
|
161 |
then
|
walther@59874
|
162 |
let
|
walther@59876
|
163 |
val id' = id_drop_sym id
|
walther@59876
|
164 |
val thm' = thm_from_thy thy id'
|
walther@60370
|
165 |
val id'' = Thm.get_name_hint thm' (*recover the thy the thm comes from*)
|
walther@59876
|
166 |
in Rule.Thm (id'', thm') end
|
walther@60370
|
167 |
else Rule.Thm (Thm.get_name_hint thm, thm) (*recover the thy the thm comes from*)
|
Walther@60645
|
168 |
| revert_sym_rule thy rule =
|
Walther@60645
|
169 |
raise ERROR ("ThmC.revert_sym_rule: NOT for " ^
|
Walther@60647
|
170 |
Rule.to_string (Proof_Context.init_global thy) rule)
|
Walther@60644
|
171 |
\<close>
|
walther@59874
|
172 |
|
walther@59907
|
173 |
|
wenzelm@60296
|
174 |
(* ML antiquotations *)
|
wenzelm@60296
|
175 |
|
wenzelm@60296
|
176 |
val sym_prefix = "sym_";
|
wenzelm@60296
|
177 |
|
wenzelm@60296
|
178 |
fun make_rule ctxt symmetric (xname, pos) =
|
wenzelm@60296
|
179 |
let
|
wenzelm@60296
|
180 |
val _ =
|
wenzelm@60296
|
181 |
if String.isPrefix sym_prefix xname
|
wenzelm@60296
|
182 |
then error ("Bad theorem name with sym-prefix " ^ quote xname ^ Position.here pos) else ();
|
wenzelm@60296
|
183 |
|
wenzelm@60296
|
184 |
val context = Context.Proof ctxt;
|
wenzelm@60296
|
185 |
val facts = Global_Theory.facts_of (Proof_Context.theory_of ctxt);
|
wenzelm@60296
|
186 |
val {name, dynamic, thms, ...} = Facts.retrieve context facts (xname, pos);
|
wenzelm@60296
|
187 |
val thm =
|
wenzelm@60296
|
188 |
if dynamic then error ("Bad dynamic fact " ^ quote name ^ Position.here pos)
|
wenzelm@60296
|
189 |
else Facts.the_single (name, pos) thms;
|
wenzelm@60296
|
190 |
val (xname', thm') = if symmetric then (sym_prefix ^ xname, thm RS sym) else (xname, thm);
|
walther@60337
|
191 |
in Rule.Thm (xname', thm') end;
|
wenzelm@60296
|
192 |
|
wenzelm@60296
|
193 |
fun antiquotation binding sym =
|
wenzelm@60296
|
194 |
ML_Antiquotation.value_embedded binding
|
wenzelm@60613
|
195 |
(Scan.lift Parse.embedded_position >> (fn name =>
|
wenzelm@60296
|
196 |
"ThmC.make_rule ML_context " ^ Bool.toString sym ^
|
wenzelm@60296
|
197 |
ML_Syntax.print_pair ML_Syntax.print_string ML_Syntax.print_position name));
|
wenzelm@60296
|
198 |
|
wenzelm@60296
|
199 |
val _ =
|
wenzelm@60296
|
200 |
Theory.setup
|
wenzelm@60296
|
201 |
(antiquotation \<^binding>\<open>rule_thm\<close> false #>
|
wenzelm@60296
|
202 |
antiquotation \<^binding>\<open>rule_thm_sym\<close> true);
|
wenzelm@60296
|
203 |
|
walther@59874
|
204 |
(**)end(**)
|