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