1 (* Title: Pure/logic.ML |
1 (* Title: Pure/logic.ML |
2 ID: $Id$ |
2 ID: $Id$ |
3 Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
3 Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
4 Copyright Cambridge University 1992 |
4 Copyright Cambridge University 1992 |
5 |
5 |
6 Supporting code for defining the abstract type "thm" |
6 Abstract syntax operations of the Pure meta-logic. |
7 *) |
7 *) |
8 |
8 |
9 infix occs; |
9 infix occs; |
10 |
10 |
11 signature LOGIC = |
11 signature LOGIC = |
12 sig |
12 sig |
13 val assum_pairs : term -> (term*term)list |
|
14 val auto_rename : bool ref |
|
15 val close_form : term -> term |
|
16 val count_prems : term * int -> int |
|
17 val dest_equals : term -> term * term |
|
18 val dest_flexpair : term -> term * term |
|
19 val dest_implies : term -> term * term |
|
20 val dest_inclass : term -> typ * class |
|
21 val dest_type : term -> typ |
|
22 val flatten_params : int -> term -> term |
|
23 val incr_indexes : typ list * int -> term -> term |
|
24 val is_all : term -> bool |
13 val is_all : term -> bool |
|
14 val mk_equals : term * term -> term |
|
15 val dest_equals : term -> term * term |
25 val is_equals : term -> bool |
16 val is_equals : term -> bool |
|
17 val mk_implies : term * term -> term |
|
18 val dest_implies : term -> term * term |
26 val is_implies : term -> bool |
19 val is_implies : term -> bool |
27 val lift_fns : term * int -> (term -> term) * (term -> term) |
20 val list_implies : term list * term -> term |
28 val list_flexpairs : (term*term)list * term -> term |
21 val strip_imp_prems : term -> term list |
29 val list_implies : term list * term -> term |
22 val strip_imp_concl : term -> term |
|
23 val strip_prems : int * term list * term -> term list * term |
|
24 val count_prems : term * int -> int |
|
25 val mk_flexpair : term * term -> term |
|
26 val dest_flexpair : term -> term * term |
|
27 val list_flexpairs : (term*term)list * term -> term |
|
28 val rule_of : (term*term)list * term list * term -> term |
|
29 val strip_flexpairs : term -> (term*term)list * term |
|
30 val skip_flexpairs : term -> term |
|
31 val strip_horn : term -> (term*term)list * term list * term |
|
32 val mk_cond_defpair : term list -> term * term -> string * term |
|
33 val mk_defpair : term * term -> string * term |
|
34 val mk_type : typ -> term |
|
35 val dest_type : term -> typ |
|
36 val mk_inclass : typ * class -> term |
|
37 val dest_inclass : term -> typ * class |
|
38 val goal_const : term |
|
39 val mk_goal : term -> term |
|
40 val dest_goal : term -> term |
|
41 val occs : term * term -> bool |
|
42 val close_form : term -> term |
|
43 val incr_indexes : typ list * int -> term -> term |
|
44 val lift_fns : term * int -> (term -> term) * (term -> term) |
|
45 val strip_assums_hyp : term -> term list |
|
46 val strip_assums_concl: term -> term |
|
47 val strip_params : term -> (string * typ) list |
|
48 val flatten_params : int -> term -> term |
|
49 val auto_rename : bool ref |
|
50 val set_rename_prefix : string -> unit |
30 val list_rename_params: string list * term -> term |
51 val list_rename_params: string list * term -> term |
31 val mk_cond_defpair : term list -> term * term -> string * term |
52 val assum_pairs : term -> (term*term)list |
32 val mk_defpair : term * term -> string * term |
53 val varify : term -> term |
33 val mk_equals : term * term -> term |
54 val unvarify : term -> term |
34 val mk_flexpair : term * term -> term |
|
35 val mk_implies : term * term -> term |
|
36 val mk_inclass : typ * class -> term |
|
37 val mk_type : typ -> term |
|
38 val occs : term * term -> bool |
|
39 val rule_of : (term*term)list * term list * term -> term |
|
40 val set_rename_prefix : string -> unit |
|
41 val skip_flexpairs : term -> term |
|
42 val strip_assums_concl: term -> term |
|
43 val strip_assums_hyp : term -> term list |
|
44 val strip_flexpairs : term -> (term*term)list * term |
|
45 val strip_horn : term -> (term*term)list * term list * term |
|
46 val strip_imp_concl : term -> term |
|
47 val strip_imp_prems : term -> term list |
|
48 val strip_params : term -> (string * typ) list |
|
49 val strip_prems : int * term list * term -> term list * term |
|
50 val unvarify : term -> term |
|
51 val varify : term -> term |
|
52 end; |
55 end; |
53 |
56 |
54 structure Logic : LOGIC = |
57 structure Logic : LOGIC = |
55 struct |
58 struct |
56 |
59 |
99 (* A1==>...An==>B goes to B, where B is not an implication *) |
102 (* A1==>...An==>B goes to B, where B is not an implication *) |
100 fun strip_imp_concl (Const("==>", _) $ A $ B) = strip_imp_concl B |
103 fun strip_imp_concl (Const("==>", _) $ A $ B) = strip_imp_concl B |
101 | strip_imp_concl A = A : term; |
104 | strip_imp_concl A = A : term; |
102 |
105 |
103 (*Strip and return premises: (i, [], A1==>...Ai==>B) |
106 (*Strip and return premises: (i, [], A1==>...Ai==>B) |
104 goes to ([Ai, A(i-1),...,A1] , B) (REVERSED) |
107 goes to ([Ai, A(i-1),...,A1] , B) (REVERSED) |
105 if i<0 or else i too big then raises TERM*) |
108 if i<0 or else i too big then raises TERM*) |
106 fun strip_prems (0, As, B) = (As, B) |
109 fun strip_prems (0, As, B) = (As, B) |
107 | strip_prems (i, As, Const("==>", _) $ A $ B) = |
110 | strip_prems (i, As, Const("==>", _) $ A $ B) = |
108 strip_prems (i-1, A::As, B) |
111 strip_prems (i-1, A::As, B) |
109 | strip_prems (_, As, A) = raise TERM("strip_prems", A::As); |
112 | strip_prems (_, As, A) = raise TERM("strip_prems", A::As); |
110 |
113 |
111 (*Count premises -- quicker than (length ostrip_prems) *) |
114 (*Count premises -- quicker than (length ostrip_prems) *) |
112 fun count_prems (Const("==>", _) $ A $ B, n) = count_prems (B,n+1) |
115 fun count_prems (Const("==>", _) $ A $ B, n) = count_prems (B,n+1) |
113 | count_prems (_,n) = n; |
116 | count_prems (_,n) = n; |
123 |
126 |
124 (*make flexflex antecedents: ( [(a1,b1),...,(an,bn)] , C ) |
127 (*make flexflex antecedents: ( [(a1,b1),...,(an,bn)] , C ) |
125 goes to (a1=?=b1) ==>...(an=?=bn)==>C *) |
128 goes to (a1=?=b1) ==>...(an=?=bn)==>C *) |
126 fun list_flexpairs ([], A) = A |
129 fun list_flexpairs ([], A) = A |
127 | list_flexpairs ((t,u)::pairs, A) = |
130 | list_flexpairs ((t,u)::pairs, A) = |
128 implies $ (mk_flexpair(t,u)) $ list_flexpairs(pairs,A); |
131 implies $ (mk_flexpair(t,u)) $ list_flexpairs(pairs,A); |
129 |
132 |
130 (*Make the object-rule tpairs==>As==>B *) |
133 (*Make the object-rule tpairs==>As==>B *) |
131 fun rule_of (tpairs, As, B) = list_flexpairs(tpairs, list_implies(As, B)); |
134 fun rule_of (tpairs, As, B) = list_flexpairs(tpairs, list_implies(As, B)); |
132 |
135 |
133 (*Remove and return flexflex pairs: |
136 (*Remove and return flexflex pairs: |
134 (a1=?=b1)==>...(an=?=bn)==>C to ( [(a1,b1),...,(an,bn)] , C ) |
137 (a1=?=b1)==>...(an=?=bn)==>C to ( [(a1,b1),...,(an,bn)] , C ) |
135 [Tail recursive in order to return a pair of results] *) |
138 [Tail recursive in order to return a pair of results] *) |
136 fun strip_flex_aux (pairs, Const("==>", _) $ (Const("=?=",_)$t$u) $ C) = |
139 fun strip_flex_aux (pairs, Const("==>", _) $ (Const("=?=",_)$t$u) $ C) = |
137 strip_flex_aux ((t,u)::pairs, C) |
140 strip_flex_aux ((t,u)::pairs, C) |
138 | strip_flex_aux (pairs,C) = (rev pairs, C); |
141 | strip_flex_aux (pairs,C) = (rev pairs, C); |
139 |
142 |
140 fun strip_flexpairs A = strip_flex_aux([], A); |
143 fun strip_flexpairs A = strip_flex_aux([], A); |
141 |
144 |
142 (*Discard flexflex pairs*) |
145 (*Discard flexflex pairs*) |
143 fun skip_flexpairs (Const("==>", _) $ (Const("=?=",_)$_$_) $ C) = |
146 fun skip_flexpairs (Const("==>", _) $ (Const("=?=",_)$_$_) $ C) = |
144 skip_flexpairs C |
147 skip_flexpairs C |
145 | skip_flexpairs C = C; |
148 | skip_flexpairs C = C; |
146 |
149 |
147 (*strip a proof state (Horn clause): |
150 (*strip a proof state (Horn clause): |
148 (a1==b1)==>...(am==bm)==>B1==>...Bn==>C |
151 (a1==b1)==>...(am==bm)==>B1==>...Bn==>C |
149 goes to ( [(a1,b1),...,(am,bm)] , [B1,...,Bn] , C) *) |
152 goes to ( [(a1,b1),...,(am,bm)] , [B1,...,Bn] , C) *) |
150 fun strip_horn A = |
153 fun strip_horn A = |
151 let val (tpairs,horn) = strip_flexpairs A |
154 let val (tpairs,horn) = strip_flexpairs A |
152 in (tpairs, strip_imp_prems horn, strip_imp_concl horn) end; |
155 in (tpairs, strip_imp_prems horn, strip_imp_concl horn) end; |
153 |
156 |
154 |
157 |
155 (** definitions **) |
158 (** definitions **) |
156 |
159 |
180 ((dest_type ty, Sign.class_of_const c_class) |
183 ((dest_type ty, Sign.class_of_const c_class) |
181 handle TERM _ => raise TERM ("dest_inclass", [t])) |
184 handle TERM _ => raise TERM ("dest_inclass", [t])) |
182 | dest_inclass t = raise TERM ("dest_inclass", [t]); |
185 | dest_inclass t = raise TERM ("dest_inclass", [t]); |
183 |
186 |
184 |
187 |
|
188 (** atomic goals **) |
|
189 |
|
190 val goal_const = Const ("Goal", propT --> propT); |
|
191 fun mk_goal t = goal_const $ t; |
|
192 |
|
193 fun dest_goal (Const ("Goal", _) $ t) = t |
|
194 | dest_goal t = raise TERM ("dest_goal", [t]); |
|
195 |
|
196 |
185 (*** Low-level term operations ***) |
197 (*** Low-level term operations ***) |
186 |
198 |
187 (*Does t occur in u? Or is alpha-convertible to u? |
199 (*Does t occur in u? Or is alpha-convertible to u? |
188 The term t must contain no loose bound variables*) |
200 The term t must contain no loose bound variables*) |
189 fun t occs u = exists_subterm (fn s => t aconv s) u; |
201 fun t occs u = exists_subterm (fn s => t aconv s) u; |
195 |
207 |
196 (*** Specialized operations for resolution... ***) |
208 (*** Specialized operations for resolution... ***) |
197 |
209 |
198 (*For all variables in the term, increment indexnames and lift over the Us |
210 (*For all variables in the term, increment indexnames and lift over the Us |
199 result is ?Gidx(B.(lev+n-1),...,B.lev) where lev is abstraction level *) |
211 result is ?Gidx(B.(lev+n-1),...,B.lev) where lev is abstraction level *) |
200 fun incr_indexes (Us: typ list, inc:int) t = |
212 fun incr_indexes (Us: typ list, inc:int) t = |
201 let fun incr (Var ((a,i), T), lev) = |
213 let fun incr (Var ((a,i), T), lev) = |
202 Unify.combound (Var((a, i+inc), Us---> incr_tvar inc T), |
214 Unify.combound (Var((a, i+inc), Us---> incr_tvar inc T), |
203 lev, length Us) |
215 lev, length Us) |
204 | incr (Abs (a,T,body), lev) = |
216 | incr (Abs (a,T,body), lev) = |
205 Abs (a, incr_tvar inc T, incr(body,lev+1)) |
217 Abs (a, incr_tvar inc T, incr(body,lev+1)) |
206 | incr (Const(a,T),_) = Const(a, incr_tvar inc T) |
218 | incr (Const(a,T),_) = Const(a, incr_tvar inc T) |
207 | incr (Free(a,T),_) = Free(a, incr_tvar inc T) |
219 | incr (Free(a,T),_) = Free(a, incr_tvar inc T) |
208 | incr (f$t, lev) = incr(f,lev) $ incr(t,lev) |
220 | incr (f$t, lev) = incr(f,lev) $ incr(t,lev) |
209 | incr (t,lev) = t |
221 | incr (t,lev) = t |
210 in incr(t,0) end; |
222 in incr(t,0) end; |
211 |
223 |
212 (*Make lifting functions from subgoal and increment. |
224 (*Make lifting functions from subgoal and increment. |
213 lift_abs operates on tpairs (unification constraints) |
225 lift_abs operates on tpairs (unification constraints) |
214 lift_all operates on propositions *) |
226 lift_all operates on propositions *) |
215 fun lift_fns (B,inc) = |
227 fun lift_fns (B,inc) = |
216 let fun lift_abs (Us, Const("==>", _) $ _ $ B) u = lift_abs (Us,B) u |
228 let fun lift_abs (Us, Const("==>", _) $ _ $ B) u = lift_abs (Us,B) u |
217 | lift_abs (Us, Const("all",_)$Abs(a,T,t)) u = |
229 | lift_abs (Us, Const("all",_)$Abs(a,T,t)) u = |
218 Abs(a, T, lift_abs (T::Us, t) u) |
230 Abs(a, T, lift_abs (T::Us, t) u) |
219 | lift_abs (Us, _) u = incr_indexes(rev Us, inc) u |
231 | lift_abs (Us, _) u = incr_indexes(rev Us, inc) u |
220 fun lift_all (Us, Const("==>", _) $ A $ B) u = |
232 fun lift_all (Us, Const("==>", _) $ A $ B) u = |
221 implies $ A $ lift_all (Us,B) u |
233 implies $ A $ lift_all (Us,B) u |
222 | lift_all (Us, Const("all",_)$Abs(a,T,t)) u = |
234 | lift_all (Us, Const("all",_)$Abs(a,T,t)) u = |
223 all T $ Abs(a, T, lift_all (T::Us,t) u) |
235 all T $ Abs(a, T, lift_all (T::Us,t) u) |
224 | lift_all (Us, _) u = incr_indexes(rev Us, inc) u; |
236 | lift_all (Us, _) u = incr_indexes(rev Us, inc) u; |
225 in (lift_abs([],B), lift_all([],B)) end; |
237 in (lift_abs([],B), lift_all([],B)) end; |
226 |
238 |
227 (*Strips assumptions in goal, yielding list of hypotheses. *) |
239 (*Strips assumptions in goal, yielding list of hypotheses. *) |
228 fun strip_assums_hyp (Const("==>", _) $ H $ B) = H :: strip_assums_hyp B |
240 fun strip_assums_hyp (Const("==>", _) $ H $ B) = H :: strip_assums_hyp B |
229 | strip_assums_hyp (Const("all",_)$Abs(a,T,t)) = strip_assums_hyp t |
241 | strip_assums_hyp (Const("all",_)$Abs(a,T,t)) = strip_assums_hyp t |
238 fun strip_params (Const("==>", _) $ H $ B) = strip_params B |
250 fun strip_params (Const("==>", _) $ H $ B) = strip_params B |
239 | strip_params (Const("all",_)$Abs(a,T,t)) = (a,T) :: strip_params t |
251 | strip_params (Const("all",_)$Abs(a,T,t)) = (a,T) :: strip_params t |
240 | strip_params B = []; |
252 | strip_params B = []; |
241 |
253 |
242 (*Removes the parameters from a subgoal and renumber bvars in hypotheses, |
254 (*Removes the parameters from a subgoal and renumber bvars in hypotheses, |
243 where j is the total number of parameters (precomputed) |
255 where j is the total number of parameters (precomputed) |
244 If n>0 then deletes assumption n. *) |
256 If n>0 then deletes assumption n. *) |
245 fun remove_params j n A = |
257 fun remove_params j n A = |
246 if j=0 andalso n<=0 then A (*nothing left to do...*) |
258 if j=0 andalso n<=0 then A (*nothing left to do...*) |
247 else case A of |
259 else case A of |
248 Const("==>", _) $ H $ B => |
260 Const("==>", _) $ H $ B => |
249 if n=1 then (remove_params j (n-1) B) |
261 if n=1 then (remove_params j (n-1) B) |
250 else implies $ (incr_boundvars j H) $ (remove_params j (n-1) B) |
262 else implies $ (incr_boundvars j H) $ (remove_params j (n-1) B) |
251 | Const("all",_)$Abs(a,T,t) => remove_params (j-1) n t |
263 | Const("all",_)$Abs(a,T,t) => remove_params (j-1) n t |
252 | _ => if n>0 then raise TERM("remove_params", [A]) |
264 | _ => if n>0 then raise TERM("remove_params", [A]) |
253 else A; |
265 else A; |
254 |
266 |
255 (** Auto-renaming of parameters in subgoals **) |
267 (** Auto-renaming of parameters in subgoals **) |
272 |
284 |
273 (*Move all parameters to the front of the subgoal, renaming them apart; |
285 (*Move all parameters to the front of the subgoal, renaming them apart; |
274 if n>0 then deletes assumption n. *) |
286 if n>0 then deletes assumption n. *) |
275 fun flatten_params n A = |
287 fun flatten_params n A = |
276 let val params = strip_params A; |
288 let val params = strip_params A; |
277 val vars = if !auto_rename |
289 val vars = if !auto_rename |
278 then rename_vars (!rename_prefix, params) |
290 then rename_vars (!rename_prefix, params) |
279 else ListPair.zip (variantlist(map #1 params,[]), |
291 else ListPair.zip (variantlist(map #1 params,[]), |
280 map #2 params) |
292 map #2 params) |
281 in list_all (vars, remove_params (length vars) n A) |
293 in list_all (vars, remove_params (length vars) n A) |
282 end; |
294 end; |
283 |
295 |
284 (*Makes parameters in a goal have the names supplied by the list cs.*) |
296 (*Makes parameters in a goal have the names supplied by the list cs.*) |
285 fun list_rename_params (cs, Const("==>", _) $ A $ B) = |
297 fun list_rename_params (cs, Const("==>", _) $ A $ B) = |
286 implies $ A $ list_rename_params (cs, B) |
298 implies $ A $ list_rename_params (cs, B) |
287 | list_rename_params (c::cs, Const("all",_)$Abs(_,T,t)) = |
299 | list_rename_params (c::cs, Const("all",_)$Abs(_,T,t)) = |
288 all T $ Abs(c, T, list_rename_params (cs, t)) |
300 all T $ Abs(c, T, list_rename_params (cs, t)) |
289 | list_rename_params (cs, B) = B; |
301 | list_rename_params (cs, B) = B; |
290 |
302 |
291 (*Strips assumptions in goal yielding ( [Hn,...,H1], [xm,...,x1], B ) |
303 (*Strips assumptions in goal yielding ( [Hn,...,H1], [xm,...,x1], B ) |
292 where H1,...,Hn are the hypotheses and x1...xm are the parameters. *) |
304 where H1,...,Hn are the hypotheses and x1...xm are the parameters. *) |
293 fun strip_assums_aux (Hs, params, Const("==>", _) $ H $ B) = |
305 fun strip_assums_aux (Hs, params, Const("==>", _) $ H $ B) = |
294 strip_assums_aux (H::Hs, params, B) |
306 strip_assums_aux (H::Hs, params, B) |
295 | strip_assums_aux (Hs, params, Const("all",_)$Abs(a,T,t)) = |
307 | strip_assums_aux (Hs, params, Const("all",_)$Abs(a,T,t)) = |
296 strip_assums_aux (Hs, (a,T)::params, t) |
308 strip_assums_aux (Hs, (a,T)::params, t) |
297 | strip_assums_aux (Hs, params, B) = (Hs, params, B); |
309 | strip_assums_aux (Hs, params, B) = (Hs, params, B); |
298 |
310 |
299 fun strip_assums A = strip_assums_aux ([],[],A); |
311 fun strip_assums A = strip_assums_aux ([],[],A); |
300 |
312 |
301 |
313 |
303 A is the first premise of the lifted rule, and thus has the form |
315 A is the first premise of the lifted rule, and thus has the form |
304 H1 ==> ... Hk ==> B and the pairs are (H1,B),...,(Hk,B) *) |
316 H1 ==> ... Hk ==> B and the pairs are (H1,B),...,(Hk,B) *) |
305 fun assum_pairs A = |
317 fun assum_pairs A = |
306 let val (Hs, params, B) = strip_assums A |
318 let val (Hs, params, B) = strip_assums A |
307 val D = Unify.rlist_abs(params, B) |
319 val D = Unify.rlist_abs(params, B) |
308 fun pairrev ([],pairs) = pairs |
320 fun pairrev ([],pairs) = pairs |
309 | pairrev (H::Hs,pairs) = |
321 | pairrev (H::Hs,pairs) = |
310 pairrev(Hs, (Unify.rlist_abs(params,H), D) :: pairs) |
322 pairrev(Hs, (Unify.rlist_abs(params,H), D) :: pairs) |
311 in pairrev (Hs,[]) (*WAS: map pair (rev Hs) *) |
323 in pairrev (Hs,[]) (*WAS: map pair (rev Hs) *) |
312 end; |
324 end; |
313 |
325 |
314 |
326 |
315 (*Converts Frees to Vars and TFrees to TVars so that axioms can be written |
327 (*Converts Frees to Vars and TFrees to TVars so that axioms can be written |