src/Tools/isac/Interpret/error-pattern.sml
author wneuper <Walther.Neuper@jku.at>
Mon, 01 Jan 2024 11:31:16 +0100
changeset 60789 8fa678b678e8
parent 60681 dcc82831573a
permissions -rw-r--r--
Doc/Specify_Phase 4: start use antiquotations from isar-ref
     1 (* title: Interpret/error-pattern.sml
     2    author: Walther Neuper
     3    0603
     4    (c) due to copyright terms
     5 
     6 In case a term is input, which contains an "error pattern" (provided by a mathauthor),
     7 several "fill_ins" can be presented as help for the next step.)
     8 *)
     9 
    10 signature ERROR_PATTERN =
    11 sig
    12   type id = Error_Pattern_Def.id
    13   type T = Error_Pattern_Def.T
    14   val s_to_string : Proof.context -> T list -> string
    15   val empty: T
    16 
    17   type fill_in_id = Error_Pattern_Def.fill_in_id
    18   type fill_in = Error_Pattern_Def.fill_in
    19   val fill_in_empty: fill_in
    20 
    21   val from_store: Proof.context -> Tactic.input -> id list
    22   val filled_exactly: Calc.T -> string -> string * Tactic.input
    23   val check_for: Proof.context -> term * term -> term * Env.T -> T list * Rule_Set.T -> id option
    24 
    25   val get_fill_ins: theory -> fill_in_id -> fill_in list
    26   val store_fill_ins: (fill_in_id * fill_in list) list -> theory -> theory
    27   type record
    28 (*val find_fill_ins: Calc.T -> id -> record list*)
    29   val find_fill_patterns: Calc.T -> id -> record list
    30 (*from isac_test for Minisubpbl*)
    31   val fill_from_store: Proof.context -> Subst.input option * Subst.T -> term -> id -> thm ->
    32     record list
    33   val fill_form: Proof.context -> Subst.input option * Subst.T -> thm * term -> id -> fill_in ->
    34     record option
    35 
    36 \<^isac_test>\<open>
    37   val get_fill_inss: theory -> (fill_in_id * fill_in list) list
    38   val check_for': Proof.context -> term * term -> subst -> id * term -> Rule_Set.T -> id option
    39 \<close>
    40 end
    41 
    42 (**)
    43 structure Error_Pattern(**): ERROR_PATTERN(**) =
    44 struct
    45 (**)
    46 
    47 type id = Error_Pattern_Def.id;
    48 type T = Error_Pattern_Def.T;
    49 val s_to_string = Error_Pattern_Def.s_to_string;
    50 val empty = ("e_errpatID", [ParseC.patt_opt @{theory} "?a = ?b" |> the], [@{thm refl}])
    51 
    52 type fill_in_id = Error_Pattern_Def.fill_in_id;
    53 type fill_in = Error_Pattern_Def.fill_in;
    54 val fill_in_empty = ("e_fillpatID", ParseC.patt_opt @{theory} "?a = _" |> the, "e_errpatID")
    55 
    56 type record = (fill_in_id * term * thm * Subst.input option);
    57 
    58 structure Data = Theory_Data (
    59   type T = (fill_in_id * fill_in list) list;
    60   val empty = [];
    61   val merge = merge op=;
    62   );                                                              
    63 fun get_fill_inss thy = Data.get thy
    64 fun store_fill_ins fill_in = Data.map (curry (Library.merge op=) fill_in)
    65 fun get_fill_ins thy fill_in_id =
    66   case AList.lookup (op =) (get_fill_inss thy) fill_in_id of
    67     SOME fill_ins => fill_ins
    68   | NONE => raise ERROR ("fill_ins for thm \"" ^ fill_in_id ^ "\" missing in theory \"" ^ 
    69     (thy |> ThyC.id_of) ^ "\" (and ancestors)" ^
    70     "\nTODO exception hierarchy needs to be established.")
    71 
    72 (*
    73   check if (agreed result, input formula) matches the error pattern "pat" modulo simplifier rls
    74 *)
    75 fun check_for' ctxt (res, inf) subst (id, pat) rls =
    76   let
    77     val (res', _, _, rewritten) =
    78       Rewrite.rew_sub ctxt 1 subst Rewrite_Ord.function_empty
    79         Rule_Set.empty false [] (HOLogic.Trueprop $ pat) res;
    80   in
    81     if rewritten then 
    82       let
    83         val norm_res = case Rewrite.rewrite_set_inst_ ctxt false subst rls res' of
    84             NONE => res'
    85           | SOME (norm_res, _) => norm_res
    86         val norm_inf = case Rewrite.rewrite_set_inst_ ctxt false subst rls inf of
    87             NONE => inf
    88           | SOME (norm_inf, _) => norm_inf
    89       in
    90         if norm_res = norm_inf then SOME id else NONE
    91       end
    92     else NONE
    93   end;
    94 
    95 (*
    96   check if (agreed result, input formula) matches SOME error pattern modulo simplifier rls;
    97   (prog, env) for retrieval of casual substitution for bdv in the pattern.
    98 *)
    99 fun check_for ctxt (res, inf) (prog, env) (errpats, rls) =
   100   let
   101     val (_, subst) = Subst.for_bdv ctxt prog env
   102     fun scan (_, [], _) = NONE
   103       | scan (id, T :: errpats, _) =
   104           case check_for' ctxt (res, inf) subst (id, T) rls of
   105             NONE => scan (id, errpats, [])
   106           | SOME id => SOME id
   107     fun scans [] = NONE
   108       | scans (group :: groups) =
   109           case scan group of
   110             NONE => scans groups
   111           | SOME id => SOME id
   112   in scans errpats end;
   113 
   114 (* fill-in patterns an forms.
   115   returns thm required by "fun in_fillform *)
   116 fun fill_form ctxt (subs_opt, subst) (thm, form) id (fillpatID, pat, erpaID) =
   117   let
   118     val (form', _, _, rewritten) =
   119       Rewrite.rew_sub ctxt 1 subst Rewrite_Ord.function_empty Rule_Set.empty false [] (HOLogic.Trueprop $ pat) form;
   120   in (*the fillpat of the thm must be dedicated to id*)
   121     if id = erpaID andalso rewritten then
   122       SOME (fillpatID, HOLogic.mk_eq (form, form'), thm, subs_opt) 
   123     else NONE
   124   end
   125 
   126 fun fill_from_store ctxt subst form errpat_id thm =
   127   let
   128     val thm_id_long = Thm.get_name_hint thm
   129     val thm_id = ThmC.cut_longid thm_id_long
   130     val fill_ins = get_fill_ins (Proof_Context.theory_of ctxt) thm_id;
   131     val some = map (fill_form ctxt subst (thm, form) errpat_id) fill_ins;
   132   in some |> filter is_some |> map the end
   133 
   134 fun find_fill_patterns (pt, pos as (p, _): Pos.pos') id =
   135   let 
   136     val ctxt = Ctree.get_ctxt pt pos
   137     val f_curr = Ctree.get_curr_formula (pt, pos)
   138     val met_id = Ctree.get_obj Ctree.g_metID pt (Ctree.par_pblobj pt p)
   139     val (errpats, prog) = (* after shift to Diff.thy -------vvvvvvvvvvvvvvv ctxt should be sufficient*)
   140       case MethodC.from_store' (Know_Store.get_via_last_thy "Build_Thydata") met_id of
   141         {errpats, program = Rule.Prog prog, ...} => (errpats, prog)
   142       | _ => error "find_fill_patterns: uncovered case of MethodC.from_store ctxt"
   143     val {env, ...} = Ctree.get_istate_LI pt pos |> Istate.the_pstate
   144     val subst = Subst.for_bdv ctxt prog env
   145     val errpat_thms = errpats
   146       |> filter ((curry op = id) o (#1: Error_Pattern_Def.T -> Error_Pattern_Def.id))
   147       |> map (#3: Error_Pattern_Def.T -> thm list)
   148       |> flat
   149   in map (fill_from_store (Ctree.get_ctxt pt pos) subst f_curr id) errpat_thms |> flat end
   150 
   151 (*
   152   Check input on a fill-pattern:
   153   check if input is exactly equal to the rewrite from a rule
   154   which is stored at the pos where the input is stored of "ok".
   155 *)
   156 (*will come directly from PIDE --------vvvvvvvvvvv*)
   157 fun filled_exactly (pt, pos as (p, _)) (istr(*, pp*)) =
   158   let
   159     val ctxt = (Ctree.get_ctxt pt pos)
   160     val ifo = Syntax.read_term ctxt istr
   161       handle ERROR msg => error (msg (*^ Position.here pp*))
   162     val p' = Pos.lev_on p;
   163     val tac = Ctree.get_obj Ctree.g_tac pt p';
   164   in 
   165     case Solve_Step.check tac (pt, pos) of
   166       Applicable.No msg => (msg, Tactic.Tac "")
   167     | Applicable.Yes rew =>
   168         let
   169           val res = case rew of
   170            Tactic.Rewrite_Inst' (_, _, _, _, _, _, _, (res, _)) => res
   171           |Tactic.Rewrite' (_, _, _, _, _, _, (res, _)) => res
   172           | t => raise ERROR ("filled_exactly: uncovered case for " ^ Tactic.string_of ctxt t)
   173         in 
   174           if not (ifo = res) then
   175             ("input does not exactly fill the gaps", Tactic.Tac "")
   176           else ("ok", tac)
   177         end
   178   end
   179 
   180 (* fetch errpatIDs from an arbitrary tactic *)
   181 fun from_store ctxt tac =
   182   let
   183     val rls_id =
   184       case tac of
   185        Tactic.Rewrite_Set rls_id => rls_id
   186       |Tactic.Rewrite_Set_Inst (_, rls_id) => rls_id
   187       | _ => "empty"
   188   in case get_rls ctxt rls_id of
   189     Rule_Set.Repeat {errpatts, ...} => errpatts
   190   | Rule_Set.Sequence {errpatts, ...} => errpatts
   191   | Rule_Set.Rrls {errpatts, ...} => errpatts
   192   | Rule_Set.Empty => []
   193   end
   194 
   195 (**)end(**)