15481
|
1 |
(* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *)
|
|
2 |
(* Title: libs/isa_fterm.ML
|
|
3 |
Author: Lucas Dixon, University of Edinburgh
|
|
4 |
lucasd@dai.ed.ac.uk
|
|
5 |
Date: 16 April 2003
|
|
6 |
*)
|
|
7 |
(* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *)
|
|
8 |
(* DESCRIPTION:
|
|
9 |
|
|
10 |
Generic Foucs terms (like Zippers) instantiation for Isabelle terms.
|
|
11 |
|
|
12 |
*)
|
|
13 |
(* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *)
|
|
14 |
|
|
15 |
signature ISA_ENCODE_TERM =
|
|
16 |
F_ENCODE_TERM_SIG
|
|
17 |
where type term = Term.term type TypeT = Term.typ;
|
|
18 |
|
|
19 |
|
|
20 |
(* signature BASIC_ISA_FTERM =
|
|
21 |
FOCUS_TERM_SIG where type Term = ISA_ENCODE_TERM.Term *)
|
|
22 |
|
|
23 |
(*
|
|
24 |
signature ISA_FTERM =
|
|
25 |
sig
|
|
26 |
include F_ENCODE_TERM_SIG
|
|
27 |
|
|
28 |
val clean_match_ft :
|
|
29 |
Type.tsig ->
|
|
30 |
FcTerm ->
|
|
31 |
Term.term ->
|
|
32 |
(
|
|
33 |
((Term.indexname * Term.typ) list * (Term.indexname * Term.term) list)
|
15531
|
34 |
* (string * Type) list * Term.term) option
|
15481
|
35 |
val clean_unify_ft :
|
|
36 |
Sign.sg ->
|
|
37 |
int ->
|
|
38 |
FcTerm ->
|
|
39 |
Term.term ->
|
|
40 |
(
|
|
41 |
((Term.indexname * Term.typ) list * (Term.indexname * Term.term) list)
|
|
42 |
* (string * Type) list * Term.term) Seq.seq
|
|
43 |
val fakefree_badbounds :
|
|
44 |
(string * Term.typ) list -> int -> Term.term -> Term.term
|
|
45 |
val find_fcterm_matches :
|
|
46 |
((FcTerm -> 'a) -> FcTerm -> 'b) ->
|
|
47 |
(FcTerm -> 'a) -> FcTerm -> 'b
|
|
48 |
val find_sg_concl_matches :
|
|
49 |
((FcTerm -> 'a) -> FcTerm -> 'b) ->
|
|
50 |
(FcTerm -> 'a) -> int -> EncodeIsaFTerm.term -> 'b
|
|
51 |
val find_sg_concl_thm_matches :
|
|
52 |
((FcTerm -> 'a) -> FcTerm -> 'b) ->
|
|
53 |
(FcTerm -> 'a) -> int -> Thm.thm -> 'b
|
|
54 |
val find_sg_matches :
|
|
55 |
((FcTerm -> 'a) -> FcTerm -> 'b) ->
|
|
56 |
(FcTerm -> 'a) -> int -> EncodeIsaFTerm.term -> 'b
|
|
57 |
val find_sg_thm_matches :
|
|
58 |
((FcTerm -> 'a) -> FcTerm -> 'b) ->
|
|
59 |
(FcTerm -> 'a) -> int -> Thm.thm -> 'b
|
|
60 |
val focus_to_concl : FcTerm -> FcTerm
|
|
61 |
val focus_to_concl_of_term : EncodeIsaFTerm.term -> FcTerm
|
|
62 |
val focus_to_subgoal :
|
|
63 |
int -> FcTerm -> FcTerm
|
|
64 |
val focus_to_subgoal_of_term :
|
|
65 |
int -> EncodeIsaFTerm.term -> FcTerm
|
|
66 |
val focus_to_term_goal_prem :
|
|
67 |
int * int -> EncodeIsaFTerm.term -> FcTerm
|
|
68 |
val focuseq_to_subgoals :
|
|
69 |
FcTerm -> FcTerm Seq.seq
|
|
70 |
exception isa_focus_term_exp of string
|
|
71 |
val mk_foo_match :
|
|
72 |
(Term.term -> Term.term) ->
|
|
73 |
('a * Term.typ) list -> Term.term -> Term.term
|
|
74 |
val prepmatch :
|
|
75 |
FcTerm ->
|
|
76 |
Term.term * ((string * Type) list * Term.term)
|
|
77 |
val search_bl_ru_f :
|
|
78 |
(FcTerm -> 'a Seq.seq) ->
|
|
79 |
FcTerm -> 'a Seq.seq
|
|
80 |
val search_bl_ur_f :
|
|
81 |
(FcTerm -> 'a Seq.seq) ->
|
|
82 |
FcTerm -> 'a Seq.seq
|
|
83 |
val valid_match_start : FcTerm -> bool
|
|
84 |
|
|
85 |
end *)
|
|
86 |
|
|
87 |
structure BasicIsaFTerm =
|
|
88 |
FocusTermFUN( structure EncodeTerm = EncodeIsaFTerm);
|
|
89 |
|
|
90 |
(* HOL Dependent *)
|
|
91 |
structure IsaFTerm =
|
|
92 |
struct
|
|
93 |
|
|
94 |
(* include BasicIsaFTerm *)
|
|
95 |
(* open FocusTermFUN( structure EncodeTerm = EncodeIsaFTerm ); *)
|
|
96 |
|
|
97 |
open BasicIsaFTerm;
|
|
98 |
|
|
99 |
|
15531
|
100 |
(* SOME general search within a focus term... *)
|
15481
|
101 |
|
|
102 |
(* Note: only upterms with a free or constant are going to yeald a
|
|
103 |
match, thus if we get anything else (bound or var) skip it! This is
|
|
104 |
important if we switch to a unification net! in particular to avoid
|
|
105 |
vars. *)
|
|
106 |
|
|
107 |
fun valid_match_start ft =
|
|
108 |
(case TermLib.bot_left_leaf_of (focus_of_fcterm ft) of
|
|
109 |
Const _ => true
|
|
110 |
| Free _ => true
|
|
111 |
| Abs _ => true
|
|
112 |
| _ => false);
|
|
113 |
|
|
114 |
(* match starting at the bottom left, moving up to top of the term,
|
|
115 |
then moving right to the next leaf and up again etc *)
|
|
116 |
(* FIXME: make properly lazy! *)
|
|
117 |
fun search_nonvar_bl_ur_f f ft =
|
|
118 |
let
|
|
119 |
val fts =
|
|
120 |
Seq.filter valid_match_start
|
|
121 |
(leaf_seq_of_fcterm ft)
|
|
122 |
|
|
123 |
fun mk_match_up_seq ft =
|
|
124 |
case focus_up_abs_or_appr ft of
|
15531
|
125 |
SOME ft' => Seq.append(f ft, mk_match_up_seq ft')
|
|
126 |
| NONE => f ft
|
15481
|
127 |
in
|
|
128 |
Seq.flat (Seq.map mk_match_up_seq fts)
|
|
129 |
end;
|
|
130 |
|
|
131 |
fun search_bl_ur_f f ft =
|
|
132 |
let
|
|
133 |
val fts = (leaf_seq_of_fcterm ft)
|
|
134 |
|
|
135 |
fun mk_match_up_seq ft =
|
|
136 |
case focus_up_abs_or_appr ft of
|
15531
|
137 |
SOME ft' => Seq.append(f ft, mk_match_up_seq ft')
|
|
138 |
| NONE => f ft
|
15481
|
139 |
in
|
|
140 |
Seq.flat (Seq.map mk_match_up_seq fts)
|
|
141 |
end;
|
|
142 |
|
|
143 |
|
|
144 |
(* FIXME: make properly lazy! *)
|
|
145 |
(* FIXME: make faking of bound vars local - for speeeeed *)
|
|
146 |
fun search_nonvar_bl_ru_f f ft =
|
|
147 |
let
|
|
148 |
fun mauxtop ft =
|
|
149 |
if (valid_match_start ft)
|
|
150 |
then maux ft else Seq.empty
|
|
151 |
and maux ft =
|
|
152 |
let val t' = (focus_of_fcterm ft)
|
|
153 |
(* val _ = writeln ("Examining: " ^ (TermLib.string_of_term t')) *)
|
|
154 |
in
|
|
155 |
(case t' of
|
|
156 |
(_ $ _) => Seq.append (maux (focus_left ft),
|
|
157 |
Seq.append(mauxtop (focus_right ft),
|
|
158 |
f ft))
|
|
159 |
| (Abs _) => Seq.append (maux (focus_abs ft),
|
|
160 |
f ft)
|
|
161 |
| leaf => f ft) end
|
|
162 |
in
|
|
163 |
mauxtop ft
|
|
164 |
end;
|
|
165 |
|
|
166 |
|
|
167 |
fun search_bl_ru_f f ft =
|
|
168 |
let
|
|
169 |
fun maux ft =
|
|
170 |
let val t' = (focus_of_fcterm ft)
|
|
171 |
(* val _ = writeln ("Examining: " ^ (TermLib.string_of_term t')) *)
|
|
172 |
in
|
|
173 |
(case t' of
|
|
174 |
(_ $ _) => Seq.append (maux (focus_left ft),
|
|
175 |
Seq.append(maux (focus_right ft),
|
|
176 |
f ft))
|
|
177 |
| (Abs _) => Seq.append (maux (focus_abs ft),
|
|
178 |
f ft)
|
|
179 |
| leaf => f ft) end
|
|
180 |
in maux ft end;
|
|
181 |
|
|
182 |
|
|
183 |
|
|
184 |
exception isa_focus_term_exp of string;
|
|
185 |
|
|
186 |
|
|
187 |
fun focus_to_dest_impl ft =
|
|
188 |
let val (lhs, rhs) =
|
|
189 |
Logic.dest_implies (focus_of_fcterm ft)
|
|
190 |
in (focus_left ft, focus_right ft) end
|
|
191 |
handle Term.TERM _ =>
|
|
192 |
raise isa_focus_term_exp
|
|
193 |
"focus_to_dest_impl: applied to non implication";
|
|
194 |
|
|
195 |
|
|
196 |
(* move focus to the conlusion *)
|
|
197 |
fun focus_to_concl ft =
|
|
198 |
let val (lhs, rhs) =
|
|
199 |
Logic.dest_implies (focus_of_fcterm ft)
|
|
200 |
in focus_to_concl (focus_right ft) end
|
|
201 |
handle Term.TERM _ => ft;
|
|
202 |
|
|
203 |
val focus_to_concl_of_term = focus_to_concl o fcterm_of_term;
|
|
204 |
|
|
205 |
|
|
206 |
|
|
207 |
(* give back sequence of focuses at different subgoals *)
|
|
208 |
(* FIXME: make truly lazy *)
|
|
209 |
fun focuseq_to_subgoals ft =
|
|
210 |
if (Logic.is_implies (focus_of_fcterm ft)) then
|
|
211 |
Seq.cons (focus_right (focus_left ft), focuseq_to_subgoals (focus_right ft))
|
|
212 |
else
|
|
213 |
Seq.empty;
|
|
214 |
|
|
215 |
(* move focus to a specific subgoal, 0 is first *)
|
|
216 |
fun focus_to_subgoal j ft =
|
|
217 |
let fun focus_to_subgoal' (ft, 0) =
|
|
218 |
let val (lhs, rhs) = Logic.dest_implies (focus_of_fcterm ft)
|
|
219 |
in ft |> focus_left |> focus_right end
|
|
220 |
| focus_to_subgoal' (ft, i) =
|
|
221 |
let val (lhs, rhs) = Logic.dest_implies (focus_of_fcterm ft)
|
|
222 |
in focus_to_subgoal' (focus_right ft, i - 1) end
|
|
223 |
in focus_to_subgoal' (ft, j - 1) end
|
|
224 |
handle Term.TERM _ =>
|
|
225 |
raise isa_focus_term_exp
|
|
226 |
("focus_to_subgoal: No such subgoal: " ^
|
|
227 |
(string_of_int j));
|
|
228 |
|
|
229 |
fun focus_to_subgoal_of_term i t =
|
|
230 |
focus_to_subgoal i (fcterm_of_term t)
|
|
231 |
|
|
232 |
(* move focus to a specific premise *)
|
|
233 |
(* fun focus_past_params i ft =
|
|
234 |
(focus_to_subgoal (focus_right ft, i))
|
|
235 |
handle isa_focus_term_exp _ =>
|
|
236 |
raise isa_focus_term_exp
|
|
237 |
("focus_to_prmise: No such premise: " ^ (string_of_int i)); *)
|
|
238 |
|
|
239 |
fun focus_to_term_goal_prem (premid,gaolid) t =
|
|
240 |
focus_to_subgoal premid (focus_to_subgoal_of_term gaolid t);
|
|
241 |
|
|
242 |
|
|
243 |
|
|
244 |
|
|
245 |
(* T is outer bound vars, n is number of locally bound vars *)
|
|
246 |
fun fakefree_badbounds T n (a $ b) =
|
|
247 |
(fakefree_badbounds T n a) $ (fakefree_badbounds T n b)
|
|
248 |
| fakefree_badbounds T n (Abs(s,ty,t)) =
|
|
249 |
Abs(s,ty, fakefree_badbounds T (n + 1) t)
|
|
250 |
| fakefree_badbounds T n (b as Bound i) =
|
|
251 |
let fun mkfake_bound j [] =
|
|
252 |
raise ERROR_MESSAGE "fakefree_badbounds: bound is outside of the known types!"
|
|
253 |
| mkfake_bound 0 ((s,ty)::Ts) =
|
|
254 |
Free (RWTools.mk_fake_bound_name s,ty)
|
|
255 |
| mkfake_bound j (d::Ts) = mkfake_bound (j - 1) Ts
|
|
256 |
in if n <= i then mkfake_bound (i - n) T else b end
|
|
257 |
| fakefree_badbounds T n t = t;
|
|
258 |
|
|
259 |
|
|
260 |
(* note: outerterm is the taget with the match replaced by a bound
|
|
261 |
variable : ie: "P lhs" beocmes "%x. P x"
|
|
262 |
insts is the types of instantiations of vars in lhs
|
|
263 |
and typinsts is the type instantiations of types in the lhs
|
|
264 |
Note: Final rule is the rule lifted into the ontext of the
|
|
265 |
taget thm. *)
|
|
266 |
fun mk_foo_match mkuptermfunc Ts t =
|
|
267 |
let
|
|
268 |
val ty = Term.type_of t
|
|
269 |
val bigtype = (rev (map snd Ts)) ---> ty
|
|
270 |
fun mk_foo 0 t = t
|
|
271 |
| mk_foo i t = mk_foo (i - 1) (t $ (Bound (i - 1)))
|
|
272 |
val num_of_bnds = (length Ts)
|
|
273 |
(* foo_term = "fooabs y0 ... yn" where y's are local bounds *)
|
|
274 |
val foo_term = mk_foo num_of_bnds (Bound num_of_bnds)
|
|
275 |
in Abs("fooabs", bigtype, mkuptermfunc foo_term) end;
|
|
276 |
|
|
277 |
(* before matching we need to fake the bound vars that missing an
|
|
278 |
abstraction. In this function we additionally construct the
|
|
279 |
abstraction environment, and an outer context term (with the focus
|
|
280 |
abstracted out) for use in rewriting with RWInst.rw *)
|
|
281 |
fun prepmatch ft =
|
|
282 |
let
|
|
283 |
val t = focus_of_fcterm ft
|
|
284 |
val Ts = tyenv_of_focus ft
|
|
285 |
val t' = fakefree_badbounds Ts 0 t
|
|
286 |
fun mktermf t =
|
|
287 |
term_of_fcterm (set_focus_of_fcterm ft t)
|
|
288 |
val absterm = mk_foo_match mktermf Ts t'
|
|
289 |
in
|
|
290 |
(t', (Ts, absterm))
|
|
291 |
end;
|
|
292 |
|
|
293 |
(* matching and unification for a focus term's focus *)
|
|
294 |
fun clean_match_ft tsig pat ft =
|
|
295 |
let val (t, (Ts,absterm)) = prepmatch ft in
|
|
296 |
case TermLib.clean_match tsig (pat, t) of
|
15531
|
297 |
NONE => NONE
|
|
298 |
| SOME insts => SOME (insts, Ts, absterm) end;
|
15481
|
299 |
(* ix = max var index *)
|
|
300 |
fun clean_unify_ft sgn ix pat ft =
|
|
301 |
let val (t, (Ts,absterm)) = prepmatch ft in
|
|
302 |
Seq.map (fn insts => (insts, Ts, absterm))
|
|
303 |
(TermLib.clean_unify sgn ix (t, pat)) end;
|
|
304 |
|
|
305 |
|
|
306 |
(* THINK: ? do we not need to incremement bound indices? *)
|
|
307 |
(* THINK: it should be the search which localisaes the search to the
|
|
308 |
current focus, not this hack in the matcher... ? *)
|
|
309 |
(* find matches below this particular focus term *)
|
|
310 |
(* The search function is to find a match within a term... *)
|
|
311 |
(* the matcher is something that is applied to each node chosen by the
|
|
312 |
searchf and the results are flattened to form a lazy list. *)
|
|
313 |
fun find_fcterm_matches searchf matcher ft =
|
|
314 |
let
|
|
315 |
val ftupterm = upterm_of ft
|
|
316 |
val focusft = focus_of_fcterm ft
|
|
317 |
val add_uptermf = add_upterm ftupterm
|
|
318 |
in
|
|
319 |
searchf
|
|
320 |
(fn ft' => matcher (add_uptermf ft'))
|
|
321 |
(fcterm_of_term focusft)
|
|
322 |
end;
|
|
323 |
|
|
324 |
(* FIXME: move argument orders for efficiency...
|
|
325 |
i.e. wenzel style val foofunc = x o y;
|
|
326 |
*)
|
|
327 |
|
|
328 |
(* find the matches inside subgoal i of th *)
|
|
329 |
fun find_sg_matches searchf matcher i t =
|
|
330 |
let val subgoal_fcterm = focus_to_subgoal_of_term i t
|
|
331 |
in find_fcterm_matches searchf matcher subgoal_fcterm end;
|
|
332 |
|
|
333 |
(* find the matches inside subgoal i of th *)
|
|
334 |
fun find_sg_thm_matches searchf matcher i th =
|
|
335 |
find_sg_matches searchf matcher i (Thm.prop_of th);
|
|
336 |
|
|
337 |
|
|
338 |
(* find the matches inside subgoal i's conclusion of th *)
|
|
339 |
fun find_sg_concl_matches searchf matcher i t =
|
|
340 |
let
|
|
341 |
val subgoal_fcterm =
|
|
342 |
focus_to_concl (focus_to_subgoal_of_term i t)
|
|
343 |
in
|
|
344 |
find_fcterm_matches searchf matcher subgoal_fcterm
|
|
345 |
end;
|
|
346 |
|
|
347 |
(* find the matches inside subgoal i's conclusion of th *)
|
|
348 |
fun find_sg_concl_thm_matches searchf matcher i th =
|
|
349 |
find_sg_concl_matches searchf matcher i (Thm.prop_of th);
|
|
350 |
|
|
351 |
end;
|
|
352 |
|
|
353 |
(*
|
|
354 |
test...
|
|
355 |
|
|
356 |
f_encode_isatermS.encode (read "P a");
|
|
357 |
isafocustermS.fcterm_of_term (read "f a");
|
|
358 |
isafocustermS.term_of_fcterm it;
|
|
359 |
|
|
360 |
Goal "P b ==> P (suc b)";
|
|
361 |
|
|
362 |
TermLib.string_of_term ((focus_of_fcterm o focus_to_subgoal_of_term 1 o prop_of) (topthm()));
|
|
363 |
|
|
364 |
TermLib.string_of_term ((focus_of_fcterm o focus_to_concl o focus_to_subgoal_of_term 1 o prop_of) (topthm()));
|
|
365 |
|
|
366 |
TermLib.string_of_term ((focus_of_fcterm o focus_to_term_goal_prem (1,1) o prop_of) (topthm()));
|
|
367 |
|
|
368 |
*)
|