src/Tools/isac/MathEngBasic/thmC.sml
author wneuper <Walther.Neuper@jku.at>
Mon, 09 Jan 2023 16:40:54 +0100
changeset 60645 43e858cf9567
parent 60644 1cc81845432d
child 60647 ea7db4f4f837
permissions -rw-r--r--
eliminate use of Thy_Info 8: arg. ctxt for Rule.to_string, partially
     1 (* Title:  BaseDefinitions/thmC.sml
     2    Author: Walther Neuper
     3    (c) due to copyright terms
     4 
     5 This structure could be dropped due to improved reflection in Isabelle;
     6 but ThmC.sym_thm requires still an identifying string thm_id.
     7 *)
     8 signature THEOREM_ISAC =
     9 sig
    10   type T = ThmC_Def.T
    11   type id = ThmC_Def.id (* shortest possible *)
    12   type long_id          (* e.g. "Test.radd_left_commute"*)
    13 
    14   val cut_id: string -> id
    15   val long_id: T -> long_id
    16 
    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"*)
    20 (*val string_of:*)
    21   val string_of_thm_PIDE: Proof.context -> thm -> string
    22   val string_of_thms_PIDE: Proof.context -> thm list -> string
    23 
    24   val id_of_thm: thm -> id
    25   val of_thm: thm -> T
    26   val from_rule : Proof.context -> Rule.rule -> T
    27   val member': id list -> Rule.rule -> bool
    28 
    29   val is_sym: id -> bool
    30   val thm_from_thy: theory -> id -> thm
    31 
    32   val make_rule: Proof.context -> bool -> string * Position.T -> Rule_Def.rule
    33 
    34 \<^isac_test>\<open>
    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
    39 \<close>
    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
    43 end
    44 
    45 (**)
    46 structure ThmC(**): THEOREM_ISAC(**) =
    47 struct
    48 (**)
    49 
    50 (** types and conversions **)
    51 
    52 type T = ThmC_Def.T;
    53 type id = ThmC_Def.id;
    54 type long_id = string;
    55 
    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*)
    58 
    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;
    63 
    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)
    67   | from_rule ctxt r =
    68     raise ERROR ("ThmC.from_rule: not defined for " ^ Rule.to_string_PIDE ctxt r);
    69 
    70 \<^isac_test>\<open>
    71 fun string_of_thm_in_thy thy thm =
    72   UnparseC.term_in_ctxt (Proof_Context.init_global thy) (Thm.prop_of thm);
    73 \<close>
    74 fun member' thmIDs thm = (member op = thmIDs (Rule.thm_id thm))
    75   handle ERROR _ => false
    76 
    77 
    78 (** handle symmetric equalities, generated by deriving input terms **)
    79 
    80 fun is_sym id =
    81   case Symbol.explode id of "s" :: "y" :: "m" :: "_" :: _ => true
    82   | _ => false;
    83 fun id_drop_sym id =
    84   case Symbol.explode id of "s" :: "y" :: "m" :: "_" :: id => implode id
    85   | _ => id
    86 
    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
    91 *)
    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
    98   | "#" :: _ =>
    99       raise ERROR ("thm_from_thy not impl.for " ^ thmid)
   100   | _ =>
   101       thmid |> Global_Theory.get_thm thy
   102 
   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])
   106   | SOME eq => eq);
   107 
   108 (* A1==>...==> An ==> (Lhs = Rhs) goes to A1 ==>...==> An ==> (Rhs = Lhs) *)
   109 (*NB: careful instantiation avoids shifting of schematic variables*)
   110 fun sym_thm thm =
   111   let
   112     val thy = Thm.theory_of_thm thm;
   113     val certT = Thm.global_ctyp_of thy;
   114     val cert = Thm.global_cterm_of thy;
   115 
   116     val (lhs, rhs) = dest_eq_concl thm |> apply2 cert;
   117     val A = Thm.typ_of_cterm lhs;
   118 
   119     val sym_rule = Thm.lift_rule (Thm.cprop_of thm) @{thm sym};
   120     val (t, s) = dest_eq_concl sym_rule;
   121 
   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));
   124 
   125     val cinstT = TVars.map (K certT) instT;
   126     val cinst = Vars.make [(s', lhs), (t', rhs)];
   127   in
   128     thm
   129     |> Thm.implies_elim (Thm.instantiate (cinstT, cinst) sym_rule)
   130     |> Thm.put_name_hint (Thm.get_name_hint thm)
   131   end;
   132 
   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}
   143 
   144 (* toggles sym_* and keeps "#:" for ad-hoc theorems *)
   145 fun make_sym_rule ctxt (Rule.Thm (thmID, thm)) =
   146       let
   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)
   155 
   156 \<^isac_test>\<open>
   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)
   161       then 
   162         let 
   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)
   171 \<close>
   172 
   173 
   174 (* ML antiquotations *)
   175 
   176 val sym_prefix = "sym_";
   177 
   178 fun make_rule ctxt symmetric (xname, pos) =
   179   let
   180     val _ =
   181       if String.isPrefix sym_prefix xname
   182       then error ("Bad theorem name with sym-prefix " ^ quote xname ^ Position.here pos) else ();
   183 
   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);
   187     val thm =
   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;
   192 
   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));
   198 
   199 val _ =
   200   Theory.setup
   201     (antiquotation \<^binding>\<open>rule_thm\<close> false #>
   202      antiquotation \<^binding>\<open>rule_thm_sym\<close> true);
   203 
   204 (**)end(**)