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(**)
|