src/Tools/isac/Interpret/error-fill-pattern.sml
author Walther Neuper <walther.neuper@jku.at>
Thu, 23 Apr 2020 09:29:56 +0200
changeset 59906 cc8df204dcb6
parent 59898 68883c046963
child 59907 4c62e16e842e
permissions -rw-r--r--
separate struct. Derive
neuper@37906
     1
(* Handle user-input during the specify- and the solve-phase. 
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@59906
     7
several "fill patterns" can be presented as help for the next step.)
neuper@37906
     8
*)
neuper@37906
     9
walther@59858
    10
signature ERROR_FILL_PATTERN =
wneuper@59262
    11
sig
walther@59858
    12
  type errpatID = Rule_Def.errpatID
walther@59858
    13
  type errpat = errpatID * term list * thm list
walther@59858
    14
  val errpats2str : errpat list -> string
walther@59858
    15
walther@59906
    16
  val find_fillpatterns : Calc.T -> Error_Fill_Def.errpatID ->
walther@59906
    17
    (Error_Fill_Def.fillpatID * term * thm * Selem.subs option) list
walther@59906
    18
  val fetchErrorpatterns : Tactic.input -> Error_Fill_Def.errpatID list
walther@59775
    19
  val is_exactly_equal : Calc.T -> string -> string * Tactic.input
walther@59906
    20
walther@59906
    21
(*/------- to ThmC -------\*)
walther@59874
    22
  val rule2thm'' : Rule.rule -> ThmC.T
walther@59822
    23
  val rule2rls' : Rule.rule -> string
walther@59906
    24
(*\------- to ThmC -------/*)
walther@59906
    25
walther@59906
    26
(*/------- to LItool -------\*)
walther@59906
    27
  val mk_tacis: Rewrite_Ord.rew_ord' * 'a -> Rule_Set.T -> term * Rule.rule * (term * term list) ->
walther@59906
    28
    Tactic.input * Tactic.T * (Pos.pos' * (Istate.T * Proof.context))
walther@59906
    29
  val check_for : term * term -> term * (term * term) list ->
walther@59906
    30
    (Error_Fill_Def.errpatID * term list * 'a list) list * Rule_Set.T ->
walther@59906
    31
      Error_Fill_Def.errpatID option
walther@59906
    32
(*\------- to LItool -------/*)
walther@59906
    33
wneuper@59310
    34
(* ---- for tests only: shifted from below to remove the Warning "unused" at fun.def. --------- *)
wneuper@59310
    35
  (*  NONE *)
walther@59886
    36
(*/-------------------------------------------------------- ! aktivate for Test_Isac BEGIN ---\* )
walther@59863
    37
  val check_err_patt : term * term -> UnparseC.subst -> Error_Fill_Def.errpatID * term -> Rule_Set.T -> Error_Fill_Def.errpatID option
wneuper@59262
    38
  val get_fillform :
walther@59858
    39
     'a * (term * term) list -> 'b * term -> Error_Fill_Def.errpatID -> Error_Fill_Def.fillpat -> (Error_Fill_Def.fillpatID * term * 'b * 'a) option
wneuper@59262
    40
  val get_fillpats :
walther@59858
    41
     'a * (term * term) list -> term -> Error_Fill_Def.errpatID -> thm -> (Error_Fill_Def.fillpatID * term * thm * 'a) list
walther@59886
    42
( *\--- ! aktivate for Test_Isac END ----------------------------------------------------------/*)
wneuper@59310
    43
wneuper@59262
    44
end
walther@59822
    45
(**)
walther@59858
    46
structure Error_Fill_Pattern(**): ERROR_FILL_PATTERN(**) =
walther@59822
    47
struct
walther@59822
    48
(**)
neuper@37906
    49
walther@59858
    50
type errpatID = Rule_Def.errpatID
walther@59858
    51
walther@59822
    52
fun rule2thm'' (Rule.Thm (id, thm)) = (id, thm)
walther@59906
    53
  | rule2thm'' r = raise ERROR ("rule2thm': not defined for " ^ Rule.to_string r);
walther@59867
    54
fun rule2rls' (Rule.Rls_ rls) = Rule_Set.id rls
walther@59906
    55
  | rule2rls' r = raise ERROR ("rule2rls': not defined for " ^ Rule.to_string r);
neuper@37906
    56
wneuper@59416
    57
fun mk_tacis ro erls (t, r as Rule.Thm (id, thm), (t', a)) = 
wneuper@59571
    58
      (Tactic.Rewrite (id, thm), 
walther@59822
    59
        Tactic.Rewrite' ("Isac_Knowledge", fst ro, erls, false, rule2thm'' r, t, (t', a)),
walther@59846
    60
       (Pos.e_pos'(*to be updated before generate tacis!!!*), (Istate.Uistate, ContextC.empty)))
wneuper@59416
    61
  | mk_tacis _ _ (t, r as Rule.Rls_ rls, (t', a)) = 
walther@59822
    62
      (Tactic.Rewrite_Set (rule2rls' r), 
wneuper@59592
    63
        Tactic.Rewrite_Set' ("Isac_Knowledge", false, rls, t, (t', a)),
walther@59846
    64
       (Pos.e_pos'(*to be updated before generate tacis!!!*), (Istate.Uistate, ContextC.empty)))
walther@59868
    65
  | mk_tacis _ _ (t, r, _) = error ("mk_tacis: not impl. for " ^ Rule.to_string r ^ " at " ^ UnparseC.term t)
neuper@37906
    66
neuper@37906
    67
walther@59822
    68
(*** handle an error pattern ***)
walther@59822
    69
neuper@42428
    70
(* check if (agreed result, input formula) matches the error pattern "pat" modulo simplifier rls *)
wneuper@59405
    71
fun check_err_patt (res, inf) subst (errpatID, pat) rls =
neuper@42423
    72
  let 
neuper@42423
    73
    val (res', _, _, rewritten) =
walther@59857
    74
      Rewrite.rew_sub (ThyC.Isac()) 1 subst Rewrite_Ord.e_rew_ord Rule_Set.empty false [] (HOLogic.Trueprop $ pat) res;
neuper@42423
    75
  in
walther@59848
    76
    if rewritten then 
neuper@42423
    77
      let
walther@59854
    78
        val norm_res = case Rewrite.rewrite_set_inst_ (ThyC.Isac()) false subst rls  res' of
neuper@42423
    79
          NONE => res'
neuper@42423
    80
        | SOME (norm_res, _) => norm_res
walther@59854
    81
        val norm_inf = case Rewrite.rewrite_set_inst_ (ThyC.Isac()) false subst rls inf of
neuper@42423
    82
          NONE => inf
neuper@42423
    83
        | SOME (norm_inf, _) => norm_inf
neuper@42423
    84
      in if norm_res = norm_inf then SOME errpatID else NONE
neuper@42423
    85
      end
neuper@42423
    86
    else NONE
neuper@42423
    87
  end;
neuper@42423
    88
neuper@42428
    89
(* check if (agreed result, input formula) matches SOME error pattern modulo simplifier rls;
neuper@42428
    90
   (prog, env) for retrieval of casual substitution for bdv in the pattern. *)
walther@59844
    91
fun check_for (res, inf) (prog, env) (errpats, rls) =
neuper@42428
    92
  let
wneuper@59263
    93
    val (_, subst) = Rtools.get_bdv_subst prog env
neuper@42428
    94
    fun scan (_, [], _) = NONE
neuper@42428
    95
      | scan (errpatID, errpat :: errpats, _) =
wneuper@59405
    96
          case check_err_patt (res, inf) subst (errpatID, errpat) rls of
neuper@42428
    97
            NONE => scan (errpatID, errpats, [])
neuper@42428
    98
          | SOME errpatID => SOME errpatID
neuper@42428
    99
    fun scans [] = NONE
neuper@42428
   100
      | scans (group :: groups) =
neuper@42428
   101
          case scan group of
neuper@42428
   102
            NONE => scans groups
neuper@42428
   103
          | SOME errpatID => SOME errpatID
neuper@42428
   104
  in scans errpats end;
neuper@42428
   105
neuper@42433
   106
(* fill-in patterns an forms.
neuper@42433
   107
  returns thm required by "fun in_fillform *)
wneuper@59405
   108
fun get_fillform (subs_opt, subst) (thm, form) errpatID (fillpatID, pat, erpaID) =
neuper@42430
   109
  let
neuper@42430
   110
    val (form', _, _, rewritten) =
walther@59857
   111
      Rewrite.rew_sub (ThyC.Isac()) 1 subst Rewrite_Ord.e_rew_ord Rule_Set.empty false [] (HOLogic.Trueprop $ pat) form;
neuper@42430
   112
  in (*the fillpat of the thm must be dedicated to errpatID*)
walther@59848
   113
    if errpatID = erpaID andalso rewritten then
walther@59848
   114
      SOME (fillpatID, HOLogic.mk_eq (form, form'), thm, subs_opt) 
wneuper@59264
   115
    else NONE
wneuper@59264
   116
  end
neuper@42430
   117
neuper@42430
   118
fun get_fillpats subst form errpatID thm =
wneuper@59264
   119
  let
wneuper@59264
   120
    val thmDeriv = Thm.get_name_hint thm
wneuper@59264
   121
    val (part, thyID) = Rtools.thy_containing_thm thmDeriv
walther@59876
   122
    val theID = [part, thyID, "Theorems", ThmC.cut_id thmDeriv]
wneuper@59269
   123
    val fillpats = case Specify.get_the theID of
walther@59898
   124
      Thy_Html.Hthm {fillpats, ...} => fillpats
wneuper@59264
   125
    | _ => error "get_fillpats: uncovered case of get_the"
wneuper@59264
   126
    val some = map (get_fillform subst (thm, form) errpatID) fillpats
wneuper@59264
   127
  in some |> filter is_some |> map the end
neuper@42430
   128
walther@59846
   129
fun find_fillpatterns (pt, pos as (p, _): Pos.pos') errpatID =
neuper@42430
   130
  let 
wneuper@59276
   131
    val f_curr = Ctree.get_curr_formula (pt, pos);
wneuper@59276
   132
    val pp = Ctree.par_pblobj pt p
wneuper@59276
   133
    val (errpats, prog) = case Specify.get_met (Ctree.get_obj Ctree.g_metID pt pp) of
wneuper@59416
   134
      {errpats, scr = Rule.Prog prog, ...} => (errpats, prog)
wneuper@59264
   135
    | _ => error "find_fillpatterns: uncovered case of get_met"
walther@59807
   136
    val {env, ...} = Ctree.get_istate_LI pt pos |> Istate.the_pstate
wneuper@59263
   137
    val subst = Rtools.get_bdv_subst prog env
neuper@42430
   138
    val errpatthms = errpats
walther@59858
   139
      |> filter ((curry op = errpatID) o (#1: Error_Fill_Def.errpat -> Error_Fill_Def.errpatID))
walther@59858
   140
      |> map (#3: Error_Fill_Def.errpat -> thm list)
neuper@42430
   141
      |> flat
wneuper@59264
   142
  in map (get_fillpats subst f_curr errpatID) errpatthms |> flat end
neuper@37906
   143
walther@59906
   144
(* check if an input formula is exactly equal to the rewrite from a rule
neuper@42437
   145
   which is stored at the pos where the input is stored of "ok". *)
neuper@42437
   146
fun is_exactly_equal (pt, pos as (p, _)) istr =
walther@59881
   147
  case TermC.parseNEW (ThyC.get_theory "Isac_Knowledge" |> ThyC.to_ctxt) istr of
wneuper@59571
   148
    NONE => ("syntax error in '" ^ istr ^ "'", Tactic.Tac "")
neuper@42437
   149
  | SOME ifo => 
neuper@42437
   150
      let
walther@59757
   151
        val p' = Pos.lev_on p;
wneuper@59276
   152
        val tac = Ctree.get_obj Ctree.g_tac pt p';
neuper@42437
   153
      in 
wneuper@59272
   154
        case Applicable.applicable_in pos pt tac of
walther@59735
   155
          Applicable.Notappl msg => (msg, Tactic.Tac "")
walther@59735
   156
        | Applicable.Appl rew =>
neuper@42437
   157
            let
neuper@42437
   158
              val res = case rew of
wneuper@59571
   159
               Tactic.Rewrite_Inst' (_, _, _, _, _, _, _, (res, _)) => res
wneuper@59571
   160
              |Tactic.Rewrite' (_, _, _, _, _, _, (res, _)) => res
walther@59728
   161
              | t => error ("is_exactly_equal: uncovered case for " ^ Tactic.string_of t)
neuper@42437
   162
            in 
walther@59848
   163
              if not (ifo = res) then
walther@59848
   164
                ("input does not exactly fill the gaps", Tactic.Tac "")
neuper@42437
   165
              else ("ok", tac)
neuper@42437
   166
            end
neuper@42437
   167
      end
neuper@42437
   168
neuper@42458
   169
(* fetch errpatIDs from an arbitrary tactic *)
neuper@42458
   170
fun fetchErrorpatterns tac =
neuper@42458
   171
  let
neuper@42458
   172
    val rlsID =
neuper@42458
   173
      case tac of
wneuper@59571
   174
       Tactic.Rewrite_Set rlsID => rlsID
wneuper@59571
   175
      |Tactic.Rewrite_Set_Inst (_, rlsID) => rlsID
walther@59852
   176
      | _ => "empty"
wneuper@59592
   177
    val (part, thyID) = Rtools.thy_containing_rls "Isac_Knowledge" rlsID;
wneuper@59269
   178
    val rls = case Specify.get_the [part, thyID, "Rulesets", rlsID] of
walther@59898
   179
      Thy_Html.Hrls {thy_rls = (_, rls), ...} => rls
wneuper@59264
   180
    | _ => error "fetchErrorpatterns: uncovered case of get_the"
neuper@42458
   181
  in case rls of
walther@59851
   182
    Rule_Def.Repeat {errpatts, ...} => errpatts
walther@59878
   183
  | Rule_Set.Sequence {errpatts, ...} => errpatts
walther@59850
   184
  | Rule_Set.Rrls {errpatts, ...} => errpatts
walther@59851
   185
  | Rule_Set.Empty => []
neuper@42458
   186
  end
wneuper@59264
   187
walther@59858
   188
type errpatID = Rule_Def.errpatID
walther@59858
   189
type errpat =
walther@59858
   190
  errpatID    (* one identifier for a list of patterns                       
walther@59858
   191
                 DESIGN ?TODO: errpatID list for hierarchy of errpats ?      *)
walther@59858
   192
  * term list (* error patterns                                              *)
walther@59858
   193
  * thm list  (* thms related to error patterns; note that respective lhs 
walther@59858
   194
                 do not match (which reflects student's error).
walther@59858
   195
                 fillpatterns are stored with these thms.                    *)
walther@59858
   196
fun errpat2str (id, tms, thms) =
walther@59875
   197
  "(\"" ^ id ^ "\",\n" ^ UnparseC.terms tms ^ ",\n" ^ ThmC.string_of_thms thms
walther@59858
   198
fun errpats2str errpats = (strs2str' o (map errpat2str)) errpats
walther@59858
   199
walther@59858
   200
(**)end(**)