src/Tools/isac/MathEngBasic/thmC.sml
author wneuper <Walther.Neuper@jku.at>
Tue, 10 Jan 2023 17:07:53 +0100
changeset 60647 ea7db4f4f837
parent 60645 43e858cf9567
child 60648 976b99bcfc96
permissions -rw-r--r--
eliminate use of Thy_Info 10: arg. ctxt for Rule.to_string finished
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(**)