src/Tools/isac/MathEngBasic/thmC.sml
author wneuper <walther.neuper@jku.at>
Mon, 19 Jul 2021 18:29:46 +0200
changeset 60337 cbad4e18e91b
parent 60296 81b6519da42b
child 60360 49680d595342
permissions -rw-r--r--
cleanup after "eliminate ThmC.numerals_to_Free"
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@59876
    16
  val string_of_thm: thm -> string
walther@59876
    17
  val string_of_thms: thm list -> string
walther@59914
    18
  val id_of_thm: thm -> id
walther@59876
    19
  val of_thm: thm -> T
walther@59907
    20
  val from_rule : Rule.rule -> T
walther@60017
    21
  val member': id list -> Rule.rule -> bool
walther@59915
    22
walther@59876
    23
  val is_sym: id -> bool
walther@59915
    24
  val thm_from_thy: theory -> ThmC_Def.id -> thm
walther@59915
    25
walther@59876
    26
  val revert_sym_rule: theory -> Rule.rule -> Rule.rule
walther@59874
    27
wenzelm@60296
    28
  val make_rule: Proof.context -> bool -> string * Position.T -> Rule_Def.rule
wenzelm@60296
    29
wenzelm@60223
    30
\<^isac_test>\<open>
walther@60220
    31
  val dest_eq_concl: thm -> term * term
walther@59876
    32
  val string_of_thm_in_thy: theory -> thm -> string
walther@59876
    33
  val id_drop_sym: id -> id
wenzelm@60223
    34
\<close>
walther@59876
    35
  val make_sym_rule: Rule.rule -> Rule.rule
walther@59876
    36
  val make_sym_rule_set: Rule_Set.T -> Rule_Set.T
walther@59876
    37
  val sym_thm: thm -> thm
walther@59865
    38
end
walther@59865
    39
walther@59865
    40
(**)
walther@59865
    41
structure ThmC(**): THEOREM_ISAC(**) =
walther@59865
    42
struct
walther@59865
    43
(**)
walther@59865
    44
walther@59915
    45
(** types and conversions **)
walther@59915
    46
walther@59874
    47
type T = ThmC_Def.T;
walther@59874
    48
type id = ThmC_Def.id;
walther@59914
    49
type long_id = string;
walther@59871
    50
walther@59915
    51
fun long_id (thmID, _) = thmID |> Global_Theory.get_thm (ThyC.Isac ()) |> Thm.get_name_hint
walther@59915
    52
fun cut_id dn = last_elem (space_explode "." dn); (*the cut_id is the key into Know_Store*)
walther@59915
    53
walther@59876
    54
val string_of_thm = ThmC_Def.string_of_thm;
walther@59876
    55
val string_of_thms = ThmC_Def.string_of_thms;
walther@59875
    56
walther@59915
    57
fun id_of_thm thm = thm |> Thm.get_name_hint |> cut_id;
walther@59876
    58
fun of_thm thm = (id_of_thm thm, thm);
walther@59915
    59
fun from_rule (Rule.Thm (id, thm)) = (id, thm)
walther@59915
    60
  | from_rule r = raise ERROR ("rule2thm': not defined for " ^ Rule.to_string r);
wenzelm@60223
    61
\<^isac_test>\<open>
walther@59879
    62
fun string_of_thm_in_thy thy thm = UnparseC.term_in_ctxt (ThyC.to_ctxt thy) (Thm.prop_of thm);
wenzelm@60223
    63
\<close>
walther@60017
    64
fun member' thmIDs thm = (member op = thmIDs (Rule.thm_id thm))
walther@59914
    65
  handle ERROR _ => false
walther@59914
    66
walther@59874
    67
walther@59876
    68
(** handle symmetric equalities, generated by deriving input terms **)
walther@59876
    69
walther@59876
    70
fun is_sym id =
walther@59876
    71
  case Symbol.explode id of "s" :: "y" :: "m" :: "_" :: _ => true
walther@59876
    72
  | _ => false;
walther@59876
    73
fun id_drop_sym id =
walther@59876
    74
  case Symbol.explode id of "s" :: "y" :: "m" :: "_" :: id => implode id
walther@59876
    75
  | _ => id
walther@59872
    76
walther@59872
    77
(* get the theorem associated with the xstring-identifier;
walther@60220
    78
   if the identifier starts with "sym_" then swap "lhs = rhs" around "=";
walther@59878
    79
   in case identifiers starting with "#" come from Eval and
walther@59876
    80
   get an ad-hoc theorem (containing numerals only) -- rejected here
walther@59876
    81
*)
walther@59876
    82
fun thm_from_thy thy thmid =
walther@59872
    83
  case Symbol.explode thmid of
walther@59876
    84
    "s" :: "y" :: "m" :: "_" :: "#" :: _ =>
walther@59876
    85
      raise ERROR ("thm_from_thy not impl.for " ^ thmid)
walther@59876
    86
  | "s" :: "y" :: "m" :: "_" :: id =>
walther@60337
    87
      ((Global_Theory.get_thm thy) (implode id)) RS sym
walther@59876
    88
  | "#" :: _ =>
walther@60220
    89
      raise ERROR ("thm_from_thy not impl.for " ^ thmid)
walther@59876
    90
  | _ =>
walther@60337
    91
      thmid |> Global_Theory.get_thm thy
walther@59872
    92
wenzelm@60206
    93
fun dest_eq_concl thm =
wenzelm@60206
    94
  (case try (HOLogic.dest_eq o HOLogic.dest_Trueprop o Logic.strip_imp_concl o Thm.prop_of) thm of
wenzelm@60206
    95
    NONE => raise THM ("dest_eq_concl: conclusion needs to be HOL equality", 0, [thm])
wenzelm@60206
    96
  | SOME eq => eq);
wenzelm@60206
    97
walther@59872
    98
(* A1==>...==> An ==> (Lhs = Rhs) goes to A1 ==>...==> An ==> (Rhs = Lhs) *)
wenzelm@60206
    99
(*NB: careful instantiation avoids shifting of schematic variables*)
walther@59872
   100
fun sym_thm thm =
wenzelm@60206
   101
  let
wenzelm@60206
   102
    val thy = Thm.theory_of_thm thm;
wenzelm@60206
   103
    val certT = Thm.global_ctyp_of thy;
wenzelm@60206
   104
    val cert = Thm.global_cterm_of thy;
wenzelm@60206
   105
wenzelm@60206
   106
    val (lhs, rhs) = dest_eq_concl thm |> apply2 cert;
wenzelm@60206
   107
    val A = Thm.typ_of_cterm lhs;
wenzelm@60206
   108
wenzelm@60206
   109
    val sym_rule = Thm.lift_rule (Thm.cprop_of thm) @{thm sym};
wenzelm@60206
   110
    val (t, s) = dest_eq_concl sym_rule;
wenzelm@60206
   111
wenzelm@60206
   112
    val instT = map (rpair A) (Term.add_tvars t []);
wenzelm@60206
   113
    val (t', s') = (t, s) |> apply2 (dest_Var o Term_Subst.instantiate (instT, []));
wenzelm@60206
   114
wenzelm@60206
   115
    val cinstT = map (apsnd certT) instT;
wenzelm@60206
   116
    val cinst = [(s', lhs), (t', rhs)];
wenzelm@60222
   117
  in
wenzelm@60222
   118
    thm
wenzelm@60222
   119
    |> Thm.implies_elim (Thm.instantiate (cinstT, cinst) sym_rule)
wenzelm@60222
   120
    |> Thm.put_name_hint (Thm.get_name_hint thm)
wenzelm@60222
   121
  end;
walther@59872
   122
walther@59876
   123
fun make_sym_rule_set Rule_Set.Empty = Rule_Set.Empty
walther@59876
   124
  | make_sym_rule_set (Rule_Def.Repeat {id, scr, calc, errpatts, erls, srls, rules, rew_ord, preconds}) =
walther@59872
   125
    Rule_Def.Repeat {id = "sym_" ^ id, scr = scr, calc = calc, errpatts = errpatts, erls = erls, srls = srls, 
walther@59872
   126
      rules = rules, rew_ord = rew_ord, preconds = preconds}
walther@59878
   127
  | make_sym_rule_set (Rule_Set.Sequence {id, scr, calc, errpatts, erls, srls, rules, rew_ord, preconds}) =
walther@59878
   128
    Rule_Set.Sequence {id = "sym_" ^ id, scr = scr, calc = calc, errpatts = errpatts, erls = erls, srls = srls, 
walther@59872
   129
      rules = rules, rew_ord = rew_ord, preconds = preconds}
walther@59876
   130
  | make_sym_rule_set (Rule_Set.Rrls {id, scr, calc, errpatts, erls, prepat, rew_ord}) = 
walther@59872
   131
    Rule_Set.Rrls {id = "sym_" ^ id, scr = scr, calc = calc,  errpatts = errpatts, erls = erls,
walther@59872
   132
      prepat = prepat, rew_ord = rew_ord}
walther@59872
   133
walther@59876
   134
(* toggles sym_* and keeps "#:" for ad-hoc theorems *)
walther@59876
   135
fun make_sym_rule (Rule.Thm (thmID, thm)) =
walther@59876
   136
      let
walther@59876
   137
        val thm' = sym_thm thm
walther@59876
   138
        val thmID' = case Symbol.explode thmID of
walther@59876
   139
          "s" :: "y" :: "m" :: "_" :: id => implode id
walther@59876
   140
        | "#" :: ":" :: _ => "#: " ^ string_of_thm thm'
walther@59876
   141
        | _ => "sym_" ^ thmID
walther@59876
   142
      in Rule.Thm (thmID', thm') end
walther@59876
   143
  | make_sym_rule (Rule.Rls_ rls) = Rule.Rls_ (make_sym_rule_set rls)
walther@59962
   144
  | make_sym_rule r = raise ERROR ("make_sym_rule: not for " ^  Rule.to_string r)
walther@59872
   145
walther@59876
   146
fun revert_sym_rule thy (Rule.Thm (id, thm)) =
walther@59876
   147
      if is_sym (cut_id id)
walther@59874
   148
      then 
walther@59874
   149
        let 
walther@59876
   150
          val id' = id_drop_sym id
walther@59876
   151
          val thm' = thm_from_thy thy id'
walther@59876
   152
          val id'' = Thm.get_name_hint thm'
walther@59876
   153
        in Rule.Thm (id'', thm') end
walther@59874
   154
      else Rule.Thm (Thm.get_name_hint thm, thm)
walther@59876
   155
  | revert_sym_rule _ rule = raise ERROR ("revert_sym_rule: NOT for " ^ Rule.to_string rule)
walther@59874
   156
walther@59907
   157
wenzelm@60296
   158
(* ML antiquotations *)
wenzelm@60296
   159
wenzelm@60296
   160
val sym_prefix = "sym_";
wenzelm@60296
   161
wenzelm@60296
   162
fun make_rule ctxt symmetric (xname, pos) =
wenzelm@60296
   163
  let
wenzelm@60296
   164
    val _ =
wenzelm@60296
   165
      if String.isPrefix sym_prefix xname
wenzelm@60296
   166
      then error ("Bad theorem name with sym-prefix " ^ quote xname ^ Position.here pos) else ();
wenzelm@60296
   167
wenzelm@60296
   168
    val context = Context.Proof ctxt;
wenzelm@60296
   169
    val facts = Global_Theory.facts_of (Proof_Context.theory_of ctxt);
wenzelm@60296
   170
    val {name, dynamic, thms, ...} = Facts.retrieve context facts (xname, pos);
wenzelm@60296
   171
    val thm =
wenzelm@60296
   172
      if dynamic then error ("Bad dynamic fact " ^ quote name ^ Position.here pos)
wenzelm@60296
   173
      else Facts.the_single (name, pos) thms;
wenzelm@60296
   174
    val (xname', thm') = if symmetric then (sym_prefix ^ xname, thm RS sym) else (xname, thm);
walther@60337
   175
  in Rule.Thm (xname', thm') end;
wenzelm@60296
   176
wenzelm@60296
   177
fun antiquotation binding sym =
wenzelm@60296
   178
  ML_Antiquotation.value_embedded binding
wenzelm@60296
   179
    (Scan.lift Args.embedded_position >> (fn name =>
wenzelm@60296
   180
      "ThmC.make_rule ML_context " ^ Bool.toString sym ^
wenzelm@60296
   181
        ML_Syntax.print_pair ML_Syntax.print_string ML_Syntax.print_position name));
wenzelm@60296
   182
wenzelm@60296
   183
val _ =
wenzelm@60296
   184
  Theory.setup
wenzelm@60296
   185
    (antiquotation \<^binding>\<open>rule_thm\<close> false #>
wenzelm@60296
   186
     antiquotation \<^binding>\<open>rule_thm_sym\<close> true);
wenzelm@60296
   187
walther@59874
   188
(**)end(**)