|
1 (* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *) |
|
2 (* Title: sys/rw_tools.ML |
|
3 Author: Lucas Dixon, University of Edinburgh |
|
4 lucas.dixon@ed.ac.uk |
|
5 Created: 28 May 2004 |
|
6 *) |
|
7 (* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *) |
|
8 (* DESCRIPTION: |
|
9 |
|
10 term related tools used for rewriting |
|
11 |
|
12 *) |
|
13 (* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *) |
|
14 |
|
15 signature RWTOOLS = |
|
16 sig |
|
17 end; |
|
18 |
|
19 structure RWTools |
|
20 = struct |
|
21 |
|
22 (* THINKABOUT: don't need this: should be able to generate the paired |
|
23 NsTs directly ? --already implemented as ~~ |
|
24 fun join_lists ([],[]) = [] |
|
25 | join_lists (x::xs, y::ys) = (x,y) :: (join_lists (xs,ys)) |
|
26 | join_lists (_, _) = raise ERROR_MESSAGE "join_lists: unequal size lists"; |
|
27 *) |
|
28 |
|
29 (* fake free variable names for locally bound variables - these work |
|
30 as placeholders. *) |
|
31 fun dest_fake_bound_name n = |
|
32 case (explode n) of |
|
33 (":" :: realchars) => implode realchars |
|
34 | _ => n; |
|
35 fun is_fake_bound_name n = (hd (explode n) = ":"); |
|
36 fun mk_fake_bound_name n = ":" ^ n; |
|
37 |
|
38 |
|
39 |
|
40 (* fake free variable names for local meta variables - these work |
|
41 as placeholders. *) |
|
42 fun dest_fake_fix_name n = |
|
43 case (explode n) of |
|
44 ("@" :: realchars) => implode realchars |
|
45 | _ => n; |
|
46 fun is_fake_fix_name n = (hd (explode n) = "@"); |
|
47 fun mk_fake_fix_name n = "@" ^ n; |
|
48 |
|
49 |
|
50 |
|
51 (* fake free variable names for meta level bound variables *) |
|
52 fun dest_fake_all_name n = |
|
53 case (explode n) of |
|
54 ("+" :: realchars) => implode realchars |
|
55 | _ => n; |
|
56 fun is_fake_all_name n = (hd (explode n) = "+"); |
|
57 fun mk_fake_all_name n = "+" ^ n; |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 (* Ys and Ts not used, Ns are real names of faked local bounds, the |
|
63 idea is that this will be mapped to free variables thus if a free |
|
64 variable is a faked local bound then we change it to being a meta |
|
65 variable so that it can later be instantiated *) |
|
66 (* FIXME: rename this - avoid the word fix! *) |
|
67 (* note we are not really "fix"'ing the free, more like making it variable! *) |
|
68 fun trymkvar_of_fakefree (Ns, Ts) Ys (n,ty) = |
|
69 if (dest_fake_bound_name n) mem Ns then Var((n,0),ty) else Free (n,ty); |
|
70 |
|
71 (* make a var into a fixed free (ie prefixed with "@") *) |
|
72 fun mk_fakefixvar Ts ((n,i),ty) = Free(mk_fake_fix_name n, ty); |
|
73 |
|
74 |
|
75 (* mk_frees_bound: string list -> Term.term -> Term.term *) |
|
76 (* This function changes free variables to being represented as bound |
|
77 variables if the free's variable name is in the given list. The debruijn |
|
78 index is simply the position in the list *) |
|
79 (* THINKABOUT: danger of an existing free variable with the same name: fix |
|
80 this so that name conflict are avoided automatically! In the meantime, |
|
81 don't have free variables named starting with a ":" *) |
|
82 fun bounds_of_fakefrees Ys (a $ b) = |
|
83 (bounds_of_fakefrees Ys a) $ (bounds_of_fakefrees Ys b) |
|
84 | bounds_of_fakefrees Ys (Abs(n,ty,t)) = |
|
85 Abs(n,ty, bounds_of_fakefrees (n::Ys) t) |
|
86 | bounds_of_fakefrees Ys (Free (n,ty)) = |
|
87 let fun try_mk_bound_of_free (i,[]) = Free (n,ty) |
|
88 | try_mk_bound_of_free (i,(y::ys)) = |
|
89 if n = y then Bound i else try_mk_bound_of_free (i+1,ys) |
|
90 in try_mk_bound_of_free (0,Ys) end |
|
91 | bounds_of_fakefrees Ys t = t; |
|
92 |
|
93 |
|
94 (* map a function f onto each free variables *) |
|
95 fun map_to_frees f Ys (a $ b) = |
|
96 (map_to_frees f Ys a) $ (map_to_frees f Ys b) |
|
97 | map_to_frees f Ys (Abs(n,ty,t)) = |
|
98 Abs(n,ty, map_to_frees f ((n,ty)::Ys) t) |
|
99 | map_to_frees f Ys (Free a) = |
|
100 f Ys a |
|
101 | map_to_frees f Ys t = t; |
|
102 |
|
103 |
|
104 (* map a function f onto each meta variable *) |
|
105 fun map_to_vars f Ys (a $ b) = |
|
106 (map_to_vars f Ys a) $ (map_to_vars f Ys b) |
|
107 | map_to_vars f Ys (Abs(n,ty,t)) = |
|
108 Abs(n,ty, map_to_vars f ((n,ty)::Ys) t) |
|
109 | map_to_vars f Ys (Var a) = |
|
110 f Ys a |
|
111 | map_to_vars f Ys t = t; |
|
112 |
|
113 (* map a function f onto each free variables *) |
|
114 fun map_to_alls f (Const("all",allty) $ Abs(n,ty,t)) = |
|
115 let val (n2,ty2) = f (n,ty) |
|
116 in (Const("all",allty) $ Abs(n2,ty2,map_to_alls f t)) end |
|
117 | map_to_alls f x = x; |
|
118 |
|
119 (* map a function f to each type variable in a term *) |
|
120 (* implicit arg: term *) |
|
121 fun map_to_term_tvars f = |
|
122 Term.map_term_types (fn TVar(ix,ty) => f (ix,ty) | x => x); |
|
123 |
|
124 |
|
125 |
|
126 (* what if a param desn't occur in the concl? think about! Note: This |
|
127 simply fixes meta level univ bound vars as Frees. At the end, we will |
|
128 change them back to schematic vars that will then unify |
|
129 appropriactely, ie with unfake_vars *) |
|
130 fun fake_concl_of_goal gt i = |
|
131 let |
|
132 val prems = Logic.strip_imp_prems gt |
|
133 val sgt = nth_elem (i - 1, prems) |
|
134 |
|
135 val tbody = Logic.strip_imp_concl (Term.strip_all_body sgt) |
|
136 val tparams = Term.strip_all_vars sgt |
|
137 |
|
138 val fakefrees = map (fn (n, ty) => Free(mk_fake_all_name n, ty)) |
|
139 tparams |
|
140 in |
|
141 Term.subst_bounds (rev fakefrees,tbody) |
|
142 end; |
|
143 |
|
144 (* what if a param desn't occur in the concl? think about! Note: This |
|
145 simply fixes meta level univ bound vars as Frees. At the end, we will |
|
146 change them back to schematic vars that will then unify |
|
147 appropriactely, ie with unfake_vars *) |
|
148 fun fake_goal gt i = |
|
149 let |
|
150 val prems = Logic.strip_imp_prems gt |
|
151 val sgt = nth_elem (i - 1, prems) |
|
152 |
|
153 val tbody = Term.strip_all_body sgt |
|
154 val tparams = Term.strip_all_vars sgt |
|
155 |
|
156 val fakefrees = map (fn (n, ty) => Free(mk_fake_all_name n, ty)) |
|
157 tparams |
|
158 in |
|
159 Term.subst_bounds (rev fakefrees,tbody) |
|
160 end; |
|
161 |
|
162 |
|
163 (* hand written - for some reason the Isabelle version in drule is broken! |
|
164 Example? something to do with Bin Yangs examples? |
|
165 *) |
|
166 fun rename_term_bvars ns (Abs(s,ty,t)) = |
|
167 let val s2opt = Library.find_first (fn (x,y) => s = x) ns |
|
168 in case s2opt of |
|
169 None => (Abs(s,ty,rename_term_bvars ns t)) |
|
170 | Some (_,s2) => Abs(s2,ty, rename_term_bvars ns t) end |
|
171 | rename_term_bvars ns (a$b) = |
|
172 (rename_term_bvars ns a) $ (rename_term_bvars ns b) |
|
173 | rename_term_bvars _ x = x; |
|
174 |
|
175 fun rename_thm_bvars ns th = |
|
176 let val t = Thm.prop_of th |
|
177 in Thm.rename_boundvars t (rename_term_bvars ns t) th end; |
|
178 |
|
179 (* Finish this to show how it breaks! (raises the exception): |
|
180 |
|
181 exception rename_thm_bvars_exp of ((string * string) list * Thm.thm) |
|
182 |
|
183 Drule.rename_bvars ns th |
|
184 handle TERM _ => raise rename_thm_bvars_exp (ns, th); |
|
185 *) |
|
186 |
|
187 end; |