eliminate use of Thy_Info 8: arg. ctxt for Rule.to_string, partially
1 (* Title: BaseDefinitions/thmC.sml
3 (c) due to copyright terms
5 This structure could be dropped due to improved reflection in Isabelle;
6 but ThmC.sym_thm requires still an identifying string thm_id.
8 signature THEOREM_ISAC =
11 type id = ThmC_Def.id (* shortest possible *)
12 type long_id (* e.g. "Test.radd_left_commute"*)
14 val cut_id: string -> id
15 val long_id: T -> long_id
17 val string_of_thm: thm -> string
18 val string_of_thms: thm list -> string
19 (*stepwise replace ^^^ by vvv and finally rename by eliminating "_PIDE"*)
21 val string_of_thm_PIDE: Proof.context -> thm -> string
22 val string_of_thms_PIDE: Proof.context -> thm list -> string
24 val id_of_thm: thm -> id
26 val from_rule : Proof.context -> Rule.rule -> T
27 val member': id list -> Rule.rule -> bool
29 val is_sym: id -> bool
30 val thm_from_thy: theory -> id -> thm
32 val make_rule: Proof.context -> bool -> string * Position.T -> Rule_Def.rule
35 val dest_eq_concl: thm -> term * term
36 val string_of_thm_in_thy: theory -> thm -> string
37 val id_drop_sym: id -> id
38 val revert_sym_rule: theory -> Rule.rule -> Rule.rule
40 val make_sym_rule: Proof.context -> Rule.rule -> Rule.rule
41 val make_sym_rule_set: Rule_Set.T -> Rule_Set.T
42 val sym_thm: thm -> thm
46 structure ThmC(**): THEOREM_ISAC(**) =
50 (** types and conversions **)
53 type id = ThmC_Def.id;
54 type long_id = string;
56 fun long_id (thmID, _) = thmID |> Global_Theory.get_thm (ThyC.Isac ()) |> Thm.get_name_hint
57 fun cut_id dn = last_elem (space_explode "." dn); (*the cut_id is the key into Know_Store*)
59 val string_of_thm = ThmC_Def.string_of_thm;
60 val string_of_thms = ThmC_Def.string_of_thms;
61 val string_of_thm_PIDE = ThmC_Def.string_of_thm_PIDE;
62 val string_of_thms_PIDE = ThmC_Def.string_of_thms_PIDE;
64 fun id_of_thm thm = thm |> Thm.get_name_hint |> cut_id;
65 fun of_thm thm = (id_of_thm thm, thm);
66 fun from_rule _ (Rule.Thm (id, thm)) = (id, thm)
68 raise ERROR ("ThmC.from_rule: not defined for " ^ Rule.to_string_PIDE ctxt r);
71 fun string_of_thm_in_thy thy thm =
72 UnparseC.term_in_ctxt (Proof_Context.init_global thy) (Thm.prop_of thm);
74 fun member' thmIDs thm = (member op = thmIDs (Rule.thm_id thm))
75 handle ERROR _ => false
78 (** handle symmetric equalities, generated by deriving input terms **)
81 case Symbol.explode id of "s" :: "y" :: "m" :: "_" :: _ => true
84 case Symbol.explode id of "s" :: "y" :: "m" :: "_" :: id => implode id
87 (* get the theorem associated with the xstring-identifier;
88 if the identifier starts with "sym_" then swap "lhs = rhs" around "=";
89 in case identifiers starting with "#" come from Eval and
90 get an ad-hoc theorem (containing numerals only) -- rejected here
92 fun thm_from_thy thy thmid =
93 case Symbol.explode thmid of
94 "s" :: "y" :: "m" :: "_" :: "#" :: _ =>
95 raise ERROR ("thm_from_thy not impl.for " ^ thmid)
96 | "s" :: "y" :: "m" :: "_" :: id =>
97 ((Global_Theory.get_thm thy) (implode id)) RS sym
99 raise ERROR ("thm_from_thy not impl.for " ^ thmid)
101 thmid |> Global_Theory.get_thm thy
103 fun dest_eq_concl thm =
104 (case try (HOLogic.dest_eq o HOLogic.dest_Trueprop o Logic.strip_imp_concl o Thm.prop_of) thm of
105 NONE => raise THM ("dest_eq_concl: conclusion needs to be HOL equality", 0, [thm])
108 (* A1==>...==> An ==> (Lhs = Rhs) goes to A1 ==>...==> An ==> (Rhs = Lhs) *)
109 (*NB: careful instantiation avoids shifting of schematic variables*)
112 val thy = Thm.theory_of_thm thm;
113 val certT = Thm.global_ctyp_of thy;
114 val cert = Thm.global_cterm_of thy;
116 val (lhs, rhs) = dest_eq_concl thm |> apply2 cert;
117 val A = Thm.typ_of_cterm lhs;
119 val sym_rule = Thm.lift_rule (Thm.cprop_of thm) @{thm sym};
120 val (t, s) = dest_eq_concl sym_rule;
122 val instT = TVars.map (K (K A)) (TVars.build (TVars.add_tvars t));
123 val (t', s') = (t, s) |> apply2 (dest_Var o Term_Subst.instantiate (instT, Vars.empty));
125 val cinstT = TVars.map (K certT) instT;
126 val cinst = Vars.make [(s', lhs), (t', rhs)];
129 |> Thm.implies_elim (Thm.instantiate (cinstT, cinst) sym_rule)
130 |> Thm.put_name_hint (Thm.get_name_hint thm)
133 fun make_sym_rule_set Rule_Set.Empty = Rule_Set.Empty
134 | make_sym_rule_set (Rule_Def.Repeat {id, program, calc, errpatts, asm_rls, prog_rls, rules, rew_ord, preconds}) =
135 Rule_Def.Repeat {id = "sym_" ^ id, program = program, calc = calc, errpatts = errpatts, asm_rls = asm_rls, prog_rls = prog_rls,
136 rules = rules, rew_ord = rew_ord, preconds = preconds}
137 | make_sym_rule_set (Rule_Set.Sequence {id, program, calc, errpatts, asm_rls, prog_rls, rules, rew_ord, preconds}) =
138 Rule_Set.Sequence {id = "sym_" ^ id, program = program, calc = calc, errpatts = errpatts, asm_rls = asm_rls, prog_rls = prog_rls,
139 rules = rules, rew_ord = rew_ord, preconds = preconds}
140 | make_sym_rule_set (Rule_Set.Rrls {id, program, calc, errpatts, asm_rls, prepat, rew_ord}) =
141 Rule_Set.Rrls {id = "sym_" ^ id, program = program, calc = calc, errpatts = errpatts, asm_rls = asm_rls,
142 prepat = prepat, rew_ord = rew_ord}
144 (* toggles sym_* and keeps "#:" for ad-hoc theorems *)
145 fun make_sym_rule ctxt (Rule.Thm (thmID, thm)) =
147 val thm' = sym_thm thm
148 val thmID' = case Symbol.explode thmID of
149 "s" :: "y" :: "m" :: "_" :: id => implode id
150 | "#" :: ":" :: _ => "#: " ^ string_of_thm_PIDE ctxt thm'
151 | _ => "sym_" ^ thmID
152 in Rule.Thm (thmID', thm') end
153 | make_sym_rule _ (Rule.Rls_ rls) = Rule.Rls_ (make_sym_rule_set rls)
154 | make_sym_rule ctxt r = raise ERROR ("ThmC.make_sym_rule: not for " ^ Rule.to_string_PIDE ctxt r)
157 (* revert a thm RS @{thm sym} back to original thm, in case it ML\<open>is_sym\<close> *)
158 fun revert_sym_rule thy (Rule.Thm (id, thm)) =
159 (*this ^^ might come from the user, who doesn't care about thy*)
160 if is_sym (cut_id id)
163 val id' = id_drop_sym id
164 val thm' = thm_from_thy thy id'
165 val id'' = Thm.get_name_hint thm' (*recover the thy the thm comes from*)
166 in Rule.Thm (id'', thm') end
167 else Rule.Thm (Thm.get_name_hint thm, thm) (*recover the thy the thm comes from*)
168 | revert_sym_rule thy rule =
169 raise ERROR ("ThmC.revert_sym_rule: NOT for " ^
170 Rule.to_string_PIDE (Proof_Context.init_global thy) rule)
174 (* ML antiquotations *)
176 val sym_prefix = "sym_";
178 fun make_rule ctxt symmetric (xname, pos) =
181 if String.isPrefix sym_prefix xname
182 then error ("Bad theorem name with sym-prefix " ^ quote xname ^ Position.here pos) else ();
184 val context = Context.Proof ctxt;
185 val facts = Global_Theory.facts_of (Proof_Context.theory_of ctxt);
186 val {name, dynamic, thms, ...} = Facts.retrieve context facts (xname, pos);
188 if dynamic then error ("Bad dynamic fact " ^ quote name ^ Position.here pos)
189 else Facts.the_single (name, pos) thms;
190 val (xname', thm') = if symmetric then (sym_prefix ^ xname, thm RS sym) else (xname, thm);
191 in Rule.Thm (xname', thm') end;
193 fun antiquotation binding sym =
194 ML_Antiquotation.value_embedded binding
195 (Scan.lift Parse.embedded_position >> (fn name =>
196 "ThmC.make_rule ML_context " ^ Bool.toString sym ^
197 ML_Syntax.print_pair ML_Syntax.print_string ML_Syntax.print_position name));
201 (antiquotation \<^binding>\<open>rule_thm\<close> false #>
202 antiquotation \<^binding>\<open>rule_thm_sym\<close> true);