src/Tools/isac/Interpret/error-pattern.sml
author Walther Neuper <walther.neuper@jku.at>
Tue, 31 Mar 2020 15:43:33 +0200
changeset 59844 373d13915f8c
parent 59822 14817bf35bc2
child 59846 7184a26ac7d5
permissions -rw-r--r--
renaming, cleanup
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
neuper@37906
     5
*)
neuper@37906
     6
walther@59822
     7
signature ERROR_PATTERN =
wneuper@59262
     8
sig
walther@59775
     9
  val find_fillpatterns : Calc.T -> Rule.errpatID -> (Celem.fillpatID * term * thm * Selem.subs option) list
walther@59775
    10
  val is_exactly_equal : Calc.T -> string -> string * Tactic.input
wneuper@59555
    11
  val concat_deriv : 'a * ((term * term) list -> term * term -> bool) ->
wneuper@59555
    12
    Rule.rls -> Rule.rule list -> term -> term -> bool * (term * Rule.rule * (term * term list)) list
wneuper@59572
    13
  val mk_tacis: Rule.rew_ord' * 'a -> Rule.rls -> term * Rule.rule * (term * term list) -> Tactic.input * Tactic.T * (Ctree.pos' * (Istate.T * Proof.context))
walther@59822
    14
  val fetchErrorpatterns : Tactic.input -> Rule.errpatID list
walther@59844
    15
  val check_for :
wneuper@59556
    16
    term * term ->
wneuper@59556
    17
    term * (term * term) list -> (Rule.errpatID * term list * 'a list) list * Rule.rls -> Rule.errpatID option
walther@59822
    18
  val rule2thm'' : Rule.rule -> Celem.thm''
walther@59822
    19
  val rule2rls' : Rule.rule -> string
wneuper@59310
    20
(* ---- for tests only: shifted from below to remove the Warning "unused" at fun.def. --------- *)
wneuper@59310
    21
  (*  NONE *)
walther@59785
    22
(*/-------------------------------------------------------- ! aktivate for Test_Isac BEGIN ---\* )
wneuper@59262
    23
  val dropwhile' : ('a -> 'b -> bool) -> 'a list -> 'b list -> 'a list * 'b list
wneuper@59416
    24
  val rev_deriv' : 'a * Rule.rule * ('b * 'c) -> 'b * Rule.rule * ('a * 'c)
wneuper@59416
    25
  val check_err_patt : term * term -> Rule.subst -> Rule.errpatID * term -> Rule.rls -> Rule.errpatID option
wneuper@59262
    26
  val get_fillform :
wneuper@59416
    27
     'a * (term * term) list -> 'b * term -> Rule.errpatID -> Celem.fillpat -> (Celem.fillpatID * term * 'b * 'a) option
wneuper@59262
    28
  val get_fillpats :
wneuper@59416
    29
     'a * (term * term) list -> term -> Rule.errpatID -> thm -> (Celem.fillpatID * term * thm * 'a) list
walther@59785
    30
( *\--- ! aktivate for Test_Isac END ----------------------------------------------------------/*)
wneuper@59310
    31
wneuper@59262
    32
end
walther@59822
    33
(**)
walther@59822
    34
structure Error_Pattern(**): ERROR_PATTERN(**) =
walther@59822
    35
struct
walther@59822
    36
(**)
neuper@37906
    37
walther@59822
    38
fun rule2thm'' (Rule.Thm (id, thm)) = (id, thm)
walther@59822
    39
  | rule2thm'' r = error ("rule2thm': not defined for " ^ Rule.rule2str r);
walther@59822
    40
fun rule2rls' (Rule.Rls_ rls) = Rule.id_rls rls
walther@59822
    41
  | rule2rls' r = error ("rule2rls': not defined for " ^ Rule.rule2str r);
neuper@37906
    42
neuper@37906
    43
(*the lists contain eq-al elem-pairs at the beginning;
neuper@37906
    44
  return first list reverted (again) - ie. in order as required subsequently*)
neuper@37906
    45
fun dropwhile' equal (f1::f2::fs) (i1::i2::is) =
wneuper@59264
    46
    if equal f1 i1
wneuper@59264
    47
    then
wneuper@59264
    48
      if equal f2 i2 then dropwhile' equal (f2 :: fs) (i2 :: is)
wneuper@59264
    49
      else (rev (f1 :: f2 :: fs), i1 :: i2 :: is)
neuper@38031
    50
    else error "dropwhile': did not start with equal elements"
neuper@37906
    51
  | dropwhile' equal (f::fs) [i] =
wneuper@59264
    52
    if equal f i
wneuper@59264
    53
    then (rev (f::fs), [i])
neuper@38031
    54
    else error "dropwhile': did not start with equal elements"
neuper@37906
    55
  | dropwhile' equal [f] (i::is) =
wneuper@59264
    56
    if equal f i
wneuper@59264
    57
    then ([f], i::is)
wneuper@59264
    58
    else error "dropwhile': did not start with equal elements"
wneuper@59264
    59
  | dropwhile' _ _ _ = error "dropwhile': uncovered case"
neuper@37906
    60
wneuper@59264
    61
(* 040214: version for concat_deriv *)
wneuper@59263
    62
fun rev_deriv' (t, r, (t', a)) = (t', Rtools.sym_rule r, (t, a));
neuper@37906
    63
wneuper@59416
    64
fun mk_tacis ro erls (t, r as Rule.Thm (id, thm), (t', a)) = 
wneuper@59571
    65
      (Tactic.Rewrite (id, thm), 
walther@59822
    66
        Tactic.Rewrite' ("Isac_Knowledge", fst ro, erls, false, rule2thm'' r, t, (t', a)),
walther@59694
    67
       (Pos.e_pos'(*to be updated before generate tacis!!!*), (Istate.Uistate, ContextC.e_ctxt)))
wneuper@59416
    68
  | mk_tacis _ _ (t, r as Rule.Rls_ rls, (t', a)) = 
walther@59822
    69
      (Tactic.Rewrite_Set (rule2rls' r), 
wneuper@59592
    70
        Tactic.Rewrite_Set' ("Isac_Knowledge", false, rls, t, (t', a)),
walther@59694
    71
       (Pos.e_pos'(*to be updated before generate tacis!!!*), (Istate.Uistate, ContextC.e_ctxt)))
wneuper@59416
    72
  | mk_tacis _ _ (t, r, _) = error ("mk_tacis: not impl. for " ^ Rule.rule2str r ^ " at " ^ Rule.term2str t)
neuper@37906
    73
wneuper@59264
    74
(* fo = ifo excluded already in inform *)
neuper@37906
    75
fun concat_deriv rew_ord erls rules fo ifo =
neuper@55487
    76
  let 
wneuper@59416
    77
    fun derivat ([]:(term * Rule.rule * (term * term list)) list) = Rule.e_term
neuper@55487
    78
      | derivat dt = (#1 o #3 o last_elem) dt
neuper@55487
    79
    fun equal (_,_,(t1, _)) (_,_,(t2, _)) = t1=t2
walther@59822
    80
    val  fod = Rtools.make_deriv (Rule.Isac()) erls rules (snd rew_ord) NONE  fo
walther@59822
    81
    val ifod = Rtools.make_deriv (Rule.Isac()) erls rules (snd rew_ord) NONE ifo
neuper@55487
    82
  in 
neuper@55487
    83
    case (fod, ifod) of
neuper@55487
    84
      ([], []) => if fo = ifo then (true, []) else (false, [])
neuper@55487
    85
    | (fod, []) => if derivat fod = ifo then (true, fod) (*ifo is normal form*) else (false, [])
neuper@55487
    86
    | ([], ifod) => if fo = derivat ifod then (true, ((map rev_deriv') o rev) ifod) else (false, [])
neuper@55487
    87
    | (fod, ifod) =>
neuper@55487
    88
      if derivat fod = derivat ifod (*common normal form found*)
neuper@55487
    89
      then
neuper@55487
    90
        let 
neuper@55487
    91
          val (fod', rifod') = dropwhile' equal (rev fod) (rev ifod)
neuper@55487
    92
        in (true, fod' @ (map rev_deriv' rifod')) end
neuper@55487
    93
      else (false, [])
wneuper@59264
    94
  end
neuper@37906
    95
walther@59822
    96
(*** handle an error pattern ***)
walther@59822
    97
neuper@42428
    98
(* check if (agreed result, input formula) matches the error pattern "pat" modulo simplifier rls *)
wneuper@59405
    99
fun check_err_patt (res, inf) subst (errpatID, pat) rls =
neuper@42423
   100
  let 
neuper@42423
   101
    val (res', _, _, rewritten) =
walther@59822
   102
      Rewrite.rew_sub (Rule.Isac()) 1 subst Rule.e_rew_ord Rule.e_rls false [] (HOLogic.Trueprop $ pat) res;
neuper@42423
   103
  in
neuper@42423
   104
    if rewritten
neuper@42423
   105
    then 
neuper@42423
   106
      let
walther@59822
   107
        val norm_res = case Rewrite.rewrite_set_inst_ (Rule.Isac()) false subst rls  res' of
neuper@42423
   108
          NONE => res'
neuper@42423
   109
        | SOME (norm_res, _) => norm_res
walther@59822
   110
        val norm_inf = case Rewrite.rewrite_set_inst_ (Rule.Isac()) false subst rls inf of
neuper@42423
   111
          NONE => inf
neuper@42423
   112
        | SOME (norm_inf, _) => norm_inf
neuper@42423
   113
      in if norm_res = norm_inf then SOME errpatID else NONE
neuper@42423
   114
      end
neuper@42423
   115
    else NONE
neuper@42423
   116
  end;
neuper@42423
   117
neuper@42428
   118
(* check if (agreed result, input formula) matches SOME error pattern modulo simplifier rls;
neuper@42428
   119
   (prog, env) for retrieval of casual substitution for bdv in the pattern. *)
walther@59844
   120
fun check_for (res, inf) (prog, env) (errpats, rls) =
neuper@42428
   121
  let
wneuper@59263
   122
    val (_, subst) = Rtools.get_bdv_subst prog env
neuper@42428
   123
    fun scan (_, [], _) = NONE
neuper@42428
   124
      | scan (errpatID, errpat :: errpats, _) =
wneuper@59405
   125
          case check_err_patt (res, inf) subst (errpatID, errpat) rls of
neuper@42428
   126
            NONE => scan (errpatID, errpats, [])
neuper@42428
   127
          | SOME errpatID => SOME errpatID
neuper@42428
   128
    fun scans [] = NONE
neuper@42428
   129
      | scans (group :: groups) =
neuper@42428
   130
          case scan group of
neuper@42428
   131
            NONE => scans groups
neuper@42428
   132
          | SOME errpatID => SOME errpatID
neuper@42428
   133
  in scans errpats end;
neuper@42428
   134
neuper@42433
   135
(* fill-in patterns an forms.
neuper@42433
   136
  returns thm required by "fun in_fillform *)
wneuper@59405
   137
fun get_fillform (subs_opt, subst) (thm, form) errpatID (fillpatID, pat, erpaID) =
neuper@42430
   138
  let
neuper@42430
   139
    val (form', _, _, rewritten) =
walther@59822
   140
      Rewrite.rew_sub (Rule.Isac()) 1 subst Rule.e_rew_ord Rule.e_rls false [] (HOLogic.Trueprop $ pat) form;
neuper@42430
   141
  in (*the fillpat of the thm must be dedicated to errpatID*)
neuper@42430
   142
    if errpatID = erpaID andalso rewritten
wneuper@59264
   143
    then SOME (fillpatID, HOLogic.mk_eq (form, form'), thm, subs_opt) 
wneuper@59264
   144
    else NONE
wneuper@59264
   145
  end
neuper@42430
   146
neuper@42430
   147
fun get_fillpats subst form errpatID thm =
wneuper@59264
   148
  let
wneuper@59264
   149
    val thmDeriv = Thm.get_name_hint thm
wneuper@59264
   150
    val (part, thyID) = Rtools.thy_containing_thm thmDeriv
wneuper@59405
   151
    val theID = [part, thyID, "Theorems", Celem.thmID_of_derivation_name thmDeriv]
wneuper@59269
   152
    val fillpats = case Specify.get_the theID of
wneuper@59405
   153
      Celem.Hthm {fillpats, ...} => fillpats
wneuper@59264
   154
    | _ => error "get_fillpats: uncovered case of get_the"
wneuper@59264
   155
    val some = map (get_fillform subst (thm, form) errpatID) fillpats
wneuper@59264
   156
  in some |> filter is_some |> map the end
neuper@42430
   157
wneuper@59276
   158
fun find_fillpatterns (pt, pos as (p, _): Ctree.pos') errpatID =
neuper@42430
   159
  let 
wneuper@59276
   160
    val f_curr = Ctree.get_curr_formula (pt, pos);
wneuper@59276
   161
    val pp = Ctree.par_pblobj pt p
wneuper@59276
   162
    val (errpats, prog) = case Specify.get_met (Ctree.get_obj Ctree.g_metID pt pp) of
wneuper@59416
   163
      {errpats, scr = Rule.Prog prog, ...} => (errpats, prog)
wneuper@59264
   164
    | _ => error "find_fillpatterns: uncovered case of get_met"
walther@59807
   165
    val {env, ...} = Ctree.get_istate_LI pt pos |> Istate.the_pstate
wneuper@59263
   166
    val subst = Rtools.get_bdv_subst prog env
neuper@42430
   167
    val errpatthms = errpats
wneuper@59416
   168
      |> filter ((curry op = errpatID) o (#1: Rule.errpat -> Rule.errpatID))
wneuper@59416
   169
      |> map (#3: Rule.errpat -> thm list)
neuper@42430
   170
      |> flat
wneuper@59264
   171
  in map (get_fillpats subst f_curr errpatID) errpatthms |> flat end
neuper@37906
   172
neuper@42437
   173
(* check if an input formula is exactly equal the rewrite from a rule
neuper@42437
   174
   which is stored at the pos where the input is stored of "ok". *)
neuper@42437
   175
fun is_exactly_equal (pt, pos as (p, _)) istr =
wneuper@59592
   176
  case TermC.parseNEW (Celem.assoc_thy "Isac_Knowledge" |> Rule.thy2ctxt) istr of
wneuper@59571
   177
    NONE => ("syntax error in '" ^ istr ^ "'", Tactic.Tac "")
neuper@42437
   178
  | SOME ifo => 
neuper@42437
   179
      let
walther@59757
   180
        val p' = Pos.lev_on p;
wneuper@59276
   181
        val tac = Ctree.get_obj Ctree.g_tac pt p';
neuper@42437
   182
      in 
wneuper@59272
   183
        case Applicable.applicable_in pos pt tac of
walther@59735
   184
          Applicable.Notappl msg => (msg, Tactic.Tac "")
walther@59735
   185
        | Applicable.Appl rew =>
neuper@42437
   186
            let
neuper@42437
   187
              val res = case rew of
wneuper@59571
   188
               Tactic.Rewrite_Inst' (_, _, _, _, _, _, _, (res, _)) => res
wneuper@59571
   189
              |Tactic.Rewrite' (_, _, _, _, _, _, (res, _)) => res
walther@59728
   190
              | t => error ("is_exactly_equal: uncovered case for " ^ Tactic.string_of t)
neuper@42437
   191
            in 
neuper@42437
   192
              if not (ifo = res)
wneuper@59571
   193
              then ("input does not exactly fill the gaps", Tactic.Tac "")
neuper@42437
   194
              else ("ok", tac)
neuper@42437
   195
            end
neuper@42437
   196
      end
neuper@42437
   197
neuper@42458
   198
(* fetch errpatIDs from an arbitrary tactic *)
neuper@42458
   199
fun fetchErrorpatterns tac =
neuper@42458
   200
  let
neuper@42458
   201
    val rlsID =
neuper@42458
   202
      case tac of
wneuper@59571
   203
       Tactic.Rewrite_Set rlsID => rlsID
wneuper@59571
   204
      |Tactic.Rewrite_Set_Inst (_, rlsID) => rlsID
neuper@55415
   205
      | _ => "e_rls"
wneuper@59592
   206
    val (part, thyID) = Rtools.thy_containing_rls "Isac_Knowledge" rlsID;
wneuper@59269
   207
    val rls = case Specify.get_the [part, thyID, "Rulesets", rlsID] of
wneuper@59405
   208
      Celem.Hrls {thy_rls = (_, rls), ...} => rls
wneuper@59264
   209
    | _ => error "fetchErrorpatterns: uncovered case of get_the"
neuper@42458
   210
  in case rls of
wneuper@59416
   211
    Rule.Rls {errpatts, ...} => errpatts
wneuper@59416
   212
  | Rule.Seq {errpatts, ...} => errpatts
wneuper@59416
   213
  | Rule.Rrls {errpatts, ...} => errpatts
wneuper@59416
   214
  | Rule.Erls => []
neuper@42458
   215
  end
wneuper@59264
   216
wneuper@59262
   217
(**)
neuper@37906
   218
end
wneuper@59262
   219
(**)