41 |
41 |
42 structure Compute :> COMPUTE = struct |
42 structure Compute :> COMPUTE = struct |
43 |
43 |
44 open Report; |
44 open Report; |
45 |
45 |
46 datatype machine = BARRAS | BARRAS_COMPILED | HASKELL | SML |
46 datatype machine = BARRAS | BARRAS_COMPILED | HASKELL | SML |
47 |
47 |
48 (* Terms are mapped to integer codes *) |
48 (* Terms are mapped to integer codes *) |
49 structure Encode :> |
49 structure Encode :> |
50 sig |
50 sig |
51 type encoding |
51 type encoding |
52 val empty : encoding |
52 val empty : encoding |
53 val insert : term -> encoding -> int * encoding |
53 val insert : term -> encoding -> int * encoding |
54 val lookup_code : term -> encoding -> int option |
54 val lookup_code : term -> encoding -> int option |
55 val lookup_term : int -> encoding -> term option |
55 val lookup_term : int -> encoding -> term option |
56 val remove_code : int -> encoding -> encoding |
56 val remove_code : int -> encoding -> encoding |
57 val remove_term : term -> encoding -> encoding |
57 val remove_term : term -> encoding -> encoding |
58 val fold : ((term * int) -> 'a -> 'a) -> encoding -> 'a -> 'a |
58 val fold : ((term * int) -> 'a -> 'a) -> encoding -> 'a -> 'a |
59 end |
59 end |
60 = |
60 = |
61 struct |
61 struct |
62 |
62 |
63 type encoding = int * (int Termtab.table) * (term Inttab.table) |
63 type encoding = int * (int Termtab.table) * (term Inttab.table) |
64 |
64 |
65 val empty = (0, Termtab.empty, Inttab.empty) |
65 val empty = (0, Termtab.empty, Inttab.empty) |
66 |
66 |
67 fun insert t (e as (count, term2int, int2term)) = |
67 fun insert t (e as (count, term2int, int2term)) = |
68 (case Termtab.lookup term2int t of |
68 (case Termtab.lookup term2int t of |
69 NONE => (count, (count+1, Termtab.update_new (t, count) term2int, Inttab.update_new (count, t) int2term)) |
69 NONE => (count, (count+1, Termtab.update_new (t, count) term2int, Inttab.update_new (count, t) int2term)) |
70 | SOME code => (code, e)) |
70 | SOME code => (code, e)) |
71 |
71 |
72 fun lookup_code t (_, term2int, _) = Termtab.lookup term2int t |
72 fun lookup_code t (_, term2int, _) = Termtab.lookup term2int t |
73 |
73 |
74 fun lookup_term c (_, _, int2term) = Inttab.lookup int2term c |
74 fun lookup_term c (_, _, int2term) = Inttab.lookup int2term c |
86 exception Make of string; |
86 exception Make of string; |
87 exception Compute of string; |
87 exception Compute of string; |
88 |
88 |
89 local |
89 local |
90 fun make_constant t ty encoding = |
90 fun make_constant t ty encoding = |
91 let |
91 let |
92 val (code, encoding) = Encode.insert t encoding |
92 val (code, encoding) = Encode.insert t encoding |
93 in |
93 in |
94 (encoding, AbstractMachine.Const code) |
94 (encoding, AbstractMachine.Const code) |
95 end |
95 end |
96 in |
96 in |
97 |
97 |
98 fun remove_types encoding t = |
98 fun remove_types encoding t = |
99 case t of |
99 case t of |
100 Var (_, ty) => make_constant t ty encoding |
100 Var (_, ty) => make_constant t ty encoding |
101 | Free (_, ty) => make_constant t ty encoding |
101 | Free (_, ty) => make_constant t ty encoding |
102 | Const (_, ty) => make_constant t ty encoding |
102 | Const (_, ty) => make_constant t ty encoding |
103 | Abs (_, ty, t') => |
103 | Abs (_, ty, t') => |
104 let val (encoding, t'') = remove_types encoding t' in |
104 let val (encoding, t'') = remove_types encoding t' in |
105 (encoding, AbstractMachine.Abs t'') |
105 (encoding, AbstractMachine.Abs t'') |
106 end |
106 end |
107 | a $ b => |
107 | a $ b => |
108 let |
108 let |
109 val (encoding, a) = remove_types encoding a |
109 val (encoding, a) = remove_types encoding a |
110 val (encoding, b) = remove_types encoding b |
110 val (encoding, b) = remove_types encoding b |
111 in |
111 in |
112 (encoding, AbstractMachine.App (a,b)) |
112 (encoding, AbstractMachine.App (a,b)) |
113 end |
113 end |
114 | Bound b => (encoding, AbstractMachine.Var b) |
114 | Bound b => (encoding, AbstractMachine.Var b) |
115 end |
115 end |
116 |
116 |
117 local |
117 local |
118 fun type_of (Free (_, ty)) = ty |
118 fun type_of (Free (_, ty)) = ty |
196 |
196 |
197 datatype cthm = ComputeThm of term list * sort list * term |
197 datatype cthm = ComputeThm of term list * sort list * term |
198 |
198 |
199 fun thm2cthm th = |
199 fun thm2cthm th = |
200 let |
200 let |
201 val {hyps, prop, tpairs, shyps, ...} = Thm.rep_thm th |
201 val {hyps, prop, tpairs, shyps, ...} = Thm.rep_thm th |
202 val _ = if not (null tpairs) then raise Make "theorems may not contain tpairs" else () |
202 val _ = if not (null tpairs) then raise Make "theorems may not contain tpairs" else () |
203 in |
203 in |
204 ComputeThm (hyps, shyps, prop) |
204 ComputeThm (hyps, shyps, prop) |
205 end |
205 end |
206 |
206 |
207 fun make_internal machine thy stamp encoding cache_pattern_terms raw_ths = |
207 fun make_internal machine thy stamp encoding cache_pattern_terms raw_ths = |
208 let |
208 let |
209 fun transfer (x:thm) = Thm.transfer thy x |
209 fun transfer (x:thm) = Thm.transfer thy x |
210 val ths = map (thm2cthm o Thm.strip_shyps o transfer) raw_ths |
210 val ths = map (thm2cthm o Thm.strip_shyps o transfer) raw_ths |
211 |
211 |
212 fun make_pattern encoding n vars (var as AbstractMachine.Abs _) = |
212 fun make_pattern encoding n vars (var as AbstractMachine.Abs _) = |
213 raise (Make "no lambda abstractions allowed in pattern") |
213 raise (Make "no lambda abstractions allowed in pattern") |
214 | make_pattern encoding n vars (var as AbstractMachine.Var _) = |
214 | make_pattern encoding n vars (var as AbstractMachine.Var _) = |
215 raise (Make "no bound variables allowed in pattern") |
215 raise (Make "no bound variables allowed in pattern") |
216 | make_pattern encoding n vars (AbstractMachine.Const code) = |
216 | make_pattern encoding n vars (AbstractMachine.Const code) = |
217 (case the (Encode.lookup_term code encoding) of |
217 (case the (Encode.lookup_term code encoding) of |
218 Var _ => ((n+1, Inttab.update_new (code, n) vars, AbstractMachine.PVar) |
218 Var _ => ((n+1, Inttab.update_new (code, n) vars, AbstractMachine.PVar) |
219 handle Inttab.DUP _ => raise (Make "no duplicate variable in pattern allowed")) |
219 handle Inttab.DUP _ => raise (Make "no duplicate variable in pattern allowed")) |
220 | _ => (n, vars, AbstractMachine.PConst (code, []))) |
220 | _ => (n, vars, AbstractMachine.PConst (code, []))) |
221 | make_pattern encoding n vars (AbstractMachine.App (a, b)) = |
221 | make_pattern encoding n vars (AbstractMachine.App (a, b)) = |
222 let |
222 let |
223 val (n, vars, pa) = make_pattern encoding n vars a |
223 val (n, vars, pa) = make_pattern encoding n vars a |
224 val (n, vars, pb) = make_pattern encoding n vars b |
224 val (n, vars, pb) = make_pattern encoding n vars b |
225 in |
225 in |
230 (n, vars, AbstractMachine.PConst (c, args@[pb])) |
230 (n, vars, AbstractMachine.PConst (c, args@[pb])) |
231 end |
231 end |
232 |
232 |
233 fun thm2rule (encoding, hyptable, shyptable) th = |
233 fun thm2rule (encoding, hyptable, shyptable) th = |
234 let |
234 let |
235 val (ComputeThm (hyps, shyps, prop)) = th |
235 val (ComputeThm (hyps, shyps, prop)) = th |
236 val hyptable = fold (fn h => Termtab.update (h, ())) hyps hyptable |
236 val hyptable = fold (fn h => Termtab.update (h, ())) hyps hyptable |
237 val shyptable = fold (fn sh => Sorttab.update (sh, ())) shyps shyptable |
237 val shyptable = fold (fn sh => Sorttab.update (sh, ())) shyps shyptable |
238 val (prems, prop) = (Logic.strip_imp_prems prop, Logic.strip_imp_concl prop) |
238 val (prems, prop) = (Logic.strip_imp_prems prop, Logic.strip_imp_concl prop) |
239 val (a, b) = Logic.dest_equals prop |
239 val (a, b) = Logic.dest_equals prop |
240 handle TERM _ => raise (Make "theorems must be meta-level equations (with optional guards)") |
240 handle TERM _ => raise (Make "theorems must be meta-level equations (with optional guards)") |
241 val a = Envir.eta_contract a |
241 val a = Envir.eta_contract a |
242 val b = Envir.eta_contract b |
242 val b = Envir.eta_contract b |
243 val prems = map Envir.eta_contract prems |
243 val prems = map Envir.eta_contract prems |
244 |
244 |
245 val (encoding, left) = remove_types encoding a |
245 val (encoding, left) = remove_types encoding a |
246 val (encoding, right) = remove_types encoding b |
246 val (encoding, right) = remove_types encoding b |
247 fun remove_types_of_guard encoding g = |
247 fun remove_types_of_guard encoding g = |
248 (let |
248 (let |
249 val (t1, t2) = Logic.dest_equals g |
249 val (t1, t2) = Logic.dest_equals g |
250 val (encoding, t1) = remove_types encoding t1 |
250 val (encoding, t1) = remove_types encoding t1 |
251 val (encoding, t2) = remove_types encoding t2 |
251 val (encoding, t2) = remove_types encoding t2 |
252 in |
252 in |
253 (encoding, AbstractMachine.Guard (t1, t2)) |
253 (encoding, AbstractMachine.Guard (t1, t2)) |
254 end handle TERM _ => raise (Make "guards must be meta-level equations")) |
254 end handle TERM _ => raise (Make "guards must be meta-level equations")) |
255 val (encoding, prems) = fold_rev (fn p => fn (encoding, ps) => let val (e, p) = remove_types_of_guard encoding p in (e, p::ps) end) prems (encoding, []) |
255 val (encoding, prems) = fold_rev (fn p => fn (encoding, ps) => let val (e, p) = remove_types_of_guard encoding p in (e, p::ps) end) prems (encoding, []) |
256 |
256 |
257 (* Principally, a check should be made here to see if the (meta-) hyps contain any of the variables of the rule. |
257 (* Principally, a check should be made here to see if the (meta-) hyps contain any of the variables of the rule. |
258 As it is, all variables of the rule are schematic, and there are no schematic variables in meta-hyps, therefore |
258 As it is, all variables of the rule are schematic, and there are no schematic variables in meta-hyps, therefore |
259 this check can be left out. *) |
259 this check can be left out. *) |
261 val (vcount, vars, pattern) = make_pattern encoding 0 Inttab.empty left |
261 val (vcount, vars, pattern) = make_pattern encoding 0 Inttab.empty left |
262 val _ = (case pattern of |
262 val _ = (case pattern of |
263 AbstractMachine.PVar => |
263 AbstractMachine.PVar => |
264 raise (Make "patterns may not start with a variable") |
264 raise (Make "patterns may not start with a variable") |
265 (* | AbstractMachine.PConst (_, []) => |
265 (* | AbstractMachine.PConst (_, []) => |
266 (print th; raise (Make "no parameter rewrite found"))*) |
266 (print th; raise (Make "no parameter rewrite found"))*) |
267 | _ => ()) |
267 | _ => ()) |
268 |
268 |
269 (* finally, provide a function for renaming the |
269 (* finally, provide a function for renaming the |
270 pattern bound variables on the right hand side *) |
270 pattern bound variables on the right hand side *) |
271 |
271 |
272 fun rename level vars (var as AbstractMachine.Var _) = var |
272 fun rename level vars (var as AbstractMachine.Var _) = var |
273 | rename level vars (c as AbstractMachine.Const code) = |
273 | rename level vars (c as AbstractMachine.Const code) = |
274 (case Inttab.lookup vars code of |
274 (case Inttab.lookup vars code of |
275 NONE => c |
275 NONE => c |
276 | SOME n => AbstractMachine.Var (vcount-n-1+level)) |
276 | SOME n => AbstractMachine.Var (vcount-n-1+level)) |
277 | rename level vars (AbstractMachine.App (a, b)) = |
277 | rename level vars (AbstractMachine.App (a, b)) = |
278 AbstractMachine.App (rename level vars a, rename level vars b) |
278 AbstractMachine.App (rename level vars a, rename level vars b) |
279 | rename level vars (AbstractMachine.Abs m) = |
279 | rename level vars (AbstractMachine.Abs m) = |
280 AbstractMachine.Abs (rename (level+1) vars m) |
280 AbstractMachine.Abs (rename (level+1) vars m) |
281 |
281 |
282 fun rename_guard (AbstractMachine.Guard (a,b)) = |
282 fun rename_guard (AbstractMachine.Guard (a,b)) = |
283 AbstractMachine.Guard (rename 0 vars a, rename 0 vars b) |
283 AbstractMachine.Guard (rename 0 vars a, rename 0 vars b) |
284 in |
284 in |
285 ((encoding, hyptable, shyptable), (map rename_guard prems, pattern, rename 0 vars right)) |
285 ((encoding, hyptable, shyptable), (map rename_guard prems, pattern, rename 0 vars right)) |
286 end |
286 end |
287 |
287 |
288 val ((encoding, hyptable, shyptable), rules) = |
288 val ((encoding, hyptable, shyptable), rules) = |
291 val (encoding_hyptable, rule) = thm2rule encoding_hyptable th |
291 val (encoding_hyptable, rule) = thm2rule encoding_hyptable th |
292 in (encoding_hyptable, rule::rules) end) |
292 in (encoding_hyptable, rule::rules) end) |
293 ths ((encoding, Termtab.empty, Sorttab.empty), []) |
293 ths ((encoding, Termtab.empty, Sorttab.empty), []) |
294 |
294 |
295 fun make_cache_pattern t (encoding, cache_patterns) = |
295 fun make_cache_pattern t (encoding, cache_patterns) = |
296 let |
296 let |
297 val (encoding, a) = remove_types encoding t |
297 val (encoding, a) = remove_types encoding t |
298 val (_,_,p) = make_pattern encoding 0 Inttab.empty a |
298 val (_,_,p) = make_pattern encoding 0 Inttab.empty a |
299 in |
299 in |
300 (encoding, p::cache_patterns) |
300 (encoding, p::cache_patterns) |
301 end |
301 end |
302 |
302 |
303 val (encoding, cache_patterns) = fold_rev make_cache_pattern cache_pattern_terms (encoding, []) |
303 val (encoding, cache_patterns) = fold_rev make_cache_pattern cache_pattern_terms (encoding, []) |
304 |
304 |
305 fun arity (Type ("fun", [a,b])) = 1 + arity b |
305 fun arity (Type ("fun", [a,b])) = 1 + arity b |
306 | arity _ = 0 |
306 | arity _ = 0 |
307 |
307 |
308 fun make_arity (Const (s, _), i) tab = |
308 fun make_arity (Const (s, _), i) tab = |
309 (Inttab.update (i, arity (Sign.the_const_type thy s)) tab handle TYPE _ => tab) |
309 (Inttab.update (i, arity (Sign.the_const_type thy s)) tab handle TYPE _ => tab) |
310 | make_arity _ tab = tab |
310 | make_arity _ tab = tab |
311 |
311 |
312 val const_arity_tab = Encode.fold make_arity encoding Inttab.empty |
312 val const_arity_tab = Encode.fold make_arity encoding Inttab.empty |
313 fun const_arity x = Inttab.lookup const_arity_tab x |
313 fun const_arity x = Inttab.lookup const_arity_tab x |
314 |
314 |
315 val prog = |
315 val prog = |
316 case machine of |
316 case machine of |
317 BARRAS => ProgBarras (AM_Interpreter.compile cache_patterns const_arity rules) |
317 BARRAS => ProgBarras (AM_Interpreter.compile cache_patterns const_arity rules) |
318 | BARRAS_COMPILED => ProgBarrasC (AM_Compiler.compile cache_patterns const_arity rules) |
318 | BARRAS_COMPILED => ProgBarrasC (AM_Compiler.compile cache_patterns const_arity rules) |
319 | HASKELL => ProgHaskell (AM_GHC.compile cache_patterns const_arity rules) |
319 | HASKELL => ProgHaskell (AM_GHC.compile cache_patterns const_arity rules) |
320 | SML => ProgSML (AM_SML.compile cache_patterns const_arity rules) |
320 | SML => ProgSML (AM_SML.compile cache_patterns const_arity rules) |
321 |
321 |
322 fun has_witness s = not (null (Sign.witness_sorts thy [] [s])) |
322 fun has_witness s = not (null (Sign.witness_sorts thy [] [s])) |
323 |
323 |
324 val shyptable = fold Sorttab.delete (filter has_witness (Sorttab.keys (shyptable))) shyptable |
324 val shyptable = fold Sorttab.delete (filter has_witness (Sorttab.keys (shyptable))) shyptable |
325 |
325 |
326 in (Theory.check_thy thy, encoding, Termtab.keys hyptable, shyptable, prog, stamp, default_naming) end |
326 in (Theory.check_thy thy, encoding, Termtab.keys hyptable, shyptable, prog, stamp, default_naming) end |
327 |
327 |
328 fun make_with_cache machine thy cache_patterns raw_thms = Computer (ref (SOME (make_internal machine thy (ref ()) Encode.empty cache_patterns raw_thms))) |
328 fun make_with_cache machine thy cache_patterns raw_thms = Computer (ref (SOME (make_internal machine thy (ref ()) Encode.empty cache_patterns raw_thms))) |
329 |
329 |
330 fun make machine thy raw_thms = make_with_cache machine thy [] raw_thms |
330 fun make machine thy raw_thms = make_with_cache machine thy [] raw_thms |
331 |
331 |
332 fun update_with_cache computer cache_patterns raw_thms = |
332 fun update_with_cache computer cache_patterns raw_thms = |
333 let |
333 let |
334 val c = make_internal (machine_of_prog (prog_of computer)) (theory_of computer) (stamp_of computer) |
334 val c = make_internal (machine_of_prog (prog_of computer)) (theory_of computer) (stamp_of computer) |
335 (encoding_of computer) cache_patterns raw_thms |
335 (encoding_of computer) cache_patterns raw_thms |
336 val _ = (ref_of computer) := SOME c |
336 val _ = (ref_of computer) := SOME c |
337 in |
337 in |
338 () |
338 () |
339 end |
339 end |
340 |
340 |
341 fun update computer raw_thms = update_with_cache computer [] raw_thms |
341 fun update computer raw_thms = update_with_cache computer [] raw_thms |
342 |
342 |
343 fun discard computer = |
343 fun discard computer = |
344 let |
344 let |
345 val _ = |
345 val _ = |
346 case prog_of computer of |
346 case prog_of computer of |
347 ProgBarras p => AM_Interpreter.discard p |
347 ProgBarras p => AM_Interpreter.discard p |
348 | ProgBarrasC p => AM_Compiler.discard p |
348 | ProgBarrasC p => AM_Compiler.discard p |
349 | ProgHaskell p => AM_GHC.discard p |
349 | ProgHaskell p => AM_GHC.discard p |
350 | ProgSML p => AM_SML.discard p |
350 | ProgSML p => AM_SML.discard p |
351 val _ = (ref_of computer) := NONE |
351 val _ = (ref_of computer) := NONE |
352 in |
352 in |
353 () |
353 () |
354 end |
354 end |
355 |
355 |
356 fun runprog (ProgBarras p) = AM_Interpreter.run p |
356 fun runprog (ProgBarras p) = AM_Interpreter.run p |
357 | runprog (ProgBarrasC p) = AM_Compiler.run p |
357 | runprog (ProgBarrasC p) = AM_Compiler.run p |
358 | runprog (ProgHaskell p) = AM_GHC.run p |
358 | runprog (ProgHaskell p) = AM_GHC.run p |
359 | runprog (ProgSML p) = AM_SML.run p |
359 | runprog (ProgSML p) = AM_SML.run p |
360 |
360 |
361 (* ------------------------------------------------------------------------------------- *) |
361 (* ------------------------------------------------------------------------------------- *) |
362 (* An oracle for exporting theorems; must only be accessible from inside this structure! *) |
362 (* An oracle for exporting theorems; must only be accessible from inside this structure! *) |
363 (* ------------------------------------------------------------------------------------- *) |
363 (* ------------------------------------------------------------------------------------- *) |
364 |
364 |
375 |
375 |
376 fun merge_shyps shyps1 shyps2 = Sorttab.keys (add_shyps shyps2 (add_shyps shyps1 Sorttab.empty)) |
376 fun merge_shyps shyps1 shyps2 = Sorttab.keys (add_shyps shyps2 (add_shyps shyps1 Sorttab.empty)) |
377 |
377 |
378 fun export_oracle (thy, ExportThm (hyps, shyps, prop)) = |
378 fun export_oracle (thy, ExportThm (hyps, shyps, prop)) = |
379 let |
379 let |
380 val shyptab = add_shyps shyps Sorttab.empty |
380 val shyptab = add_shyps shyps Sorttab.empty |
381 fun delete s shyptab = Sorttab.delete s shyptab handle Sorttab.UNDEF _ => shyptab |
381 fun delete s shyptab = Sorttab.delete s shyptab handle Sorttab.UNDEF _ => shyptab |
382 fun delete_term t shyptab = fold delete (Sorts.insert_term t []) shyptab |
382 fun delete_term t shyptab = fold delete (Sorts.insert_term t []) shyptab |
383 fun has_witness s = not (null (Sign.witness_sorts thy [] [s])) |
383 fun has_witness s = not (null (Sign.witness_sorts thy [] [s])) |
384 val shyptab = fold Sorttab.delete (filter has_witness (Sorttab.keys (shyptab))) shyptab |
384 val shyptab = fold Sorttab.delete (filter has_witness (Sorttab.keys (shyptab))) shyptab |
385 val shyps = if Sorttab.is_empty shyptab then [] else Sorttab.keys (fold delete_term (prop::hyps) shyptab) |
385 val shyps = if Sorttab.is_empty shyptab then [] else Sorttab.keys (fold delete_term (prop::hyps) shyptab) |
386 val _ = if not (null shyps) then raise Compute ("dangling sort hypotheses: "^(makestring shyps)) else () |
386 val _ = if not (null shyps) then raise Compute ("dangling sort hypotheses: "^(makestring shyps)) else () |
387 in |
387 in |
388 fold_rev (fn hyp => fn p => Logic.mk_implies (hyp, p)) hyps prop |
388 fold_rev (fn hyp => fn p => Logic.mk_implies (hyp, p)) hyps prop |
389 end |
389 end |
390 | export_oracle _ = raise Match |
390 | export_oracle _ = raise Match |
391 |
391 |
392 val setup_compute = (fn thy => Theory.add_oracle ("compute", export_oracle) thy) |
392 val setup_compute = (fn thy => Theory.add_oracle ("compute", export_oracle) thy) |
393 |
393 |
394 fun export_thm thy hyps shyps prop = |
394 fun export_thm thy hyps shyps prop = |
395 let |
395 let |
396 val th = invoke_oracle_i thy "Compute_Oracle.compute" (thy, ExportThm (hyps, shyps, prop)) |
396 val th = invoke_oracle_i thy "Compute_Oracle.compute" (thy, ExportThm (hyps, shyps, prop)) |
397 val hyps = map (fn h => assume (cterm_of thy h)) hyps |
397 val hyps = map (fn h => assume (cterm_of thy h)) hyps |
398 in |
398 in |
399 fold (fn h => fn p => implies_elim p h) hyps th |
399 fold (fn h => fn p => implies_elim p h) hyps th |
400 end |
400 end |
401 |
401 |
402 (* --------- Rewrite ----------- *) |
402 (* --------- Rewrite ----------- *) |
403 |
403 |
404 fun rewrite computer ct = |
404 fun rewrite computer ct = |
405 let |
405 let |
406 val {t=t',T=ty,thy=thy,...} = rep_cterm ct |
406 val thy = Thm.theory_of_cterm ct |
407 val _ = Theory.assert_super (theory_of computer) thy |
407 val {t=t',T=ty,...} = rep_cterm ct |
408 val naming = naming_of computer |
408 val _ = Theory.assert_super (theory_of computer) thy |
|
409 val naming = naming_of computer |
409 val (encoding, t) = remove_types (encoding_of computer) t' |
410 val (encoding, t) = remove_types (encoding_of computer) t' |
410 (*val _ = if (!print_encoding) then writeln (makestring ("encoding: ",Encode.fold (fn x => fn s => x::s) encoding [])) else ()*) |
411 (*val _ = if (!print_encoding) then writeln (makestring ("encoding: ",Encode.fold (fn x => fn s => x::s) encoding [])) else ()*) |
411 val t = runprog (prog_of computer) t |
412 val t = runprog (prog_of computer) t |
412 val t = infer_types naming encoding ty t |
413 val t = infer_types naming encoding ty t |
413 val eq = Logic.mk_equals (t', t) |
414 val eq = Logic.mk_equals (t', t) |
414 in |
415 in |
415 export_thm thy (hyps_of computer) (Sorttab.keys (shyptab_of computer)) eq |
416 export_thm thy (hyps_of computer) (Sorttab.keys (shyptab_of computer)) eq |
416 end |
417 end |
417 |
418 |
418 (* --------- Simplify ------------ *) |
419 (* --------- Simplify ------------ *) |
419 |
420 |
420 datatype prem = EqPrem of AbstractMachine.term * AbstractMachine.term * Term.typ * int |
421 datatype prem = EqPrem of AbstractMachine.term * AbstractMachine.term * Term.typ * int |
421 | Prem of AbstractMachine.term |
422 | Prem of AbstractMachine.term |
422 datatype theorem = Theorem of theory_ref * unit ref * (int * typ) Symtab.table * (AbstractMachine.term option) Inttab.table |
423 datatype theorem = Theorem of theory_ref * unit ref * (int * typ) Symtab.table * (AbstractMachine.term option) Inttab.table |
423 * prem list * AbstractMachine.term * term list * sort list |
424 * prem list * AbstractMachine.term * term list * sort list |
424 |
425 |
425 |
426 |
426 exception ParamSimplify of computer * theorem |
427 exception ParamSimplify of computer * theorem |
437 fun collect_vars (Abs (_, _, t)) tab = collect_vars t tab |
438 fun collect_vars (Abs (_, _, t)) tab = collect_vars t tab |
438 | collect_vars (a $ b) tab = collect_vars b (collect_vars a tab) |
439 | collect_vars (a $ b) tab = collect_vars b (collect_vars a tab) |
439 | collect_vars (Const _) tab = tab |
440 | collect_vars (Const _) tab = tab |
440 | collect_vars (Free _) tab = tab |
441 | collect_vars (Free _) tab = tab |
441 | collect_vars (Var ((s, i), ty)) tab = |
442 | collect_vars (Var ((s, i), ty)) tab = |
442 if List.find (fn x => x=s) vars = NONE then |
443 if List.find (fn x => x=s) vars = NONE then |
443 tab |
444 tab |
444 else |
445 else |
445 (case Symtab.lookup tab s of |
446 (case Symtab.lookup tab s of |
446 SOME ((s',i'),ty') => |
447 SOME ((s',i'),ty') => |
447 if s' <> s orelse i' <> i orelse ty <> ty' then |
448 if s' <> s orelse i' <> i orelse ty <> ty' then |
448 raise Compute ("make_theorem: variable name '"^s^"' is not unique") |
449 raise Compute ("make_theorem: variable name '"^s^"' is not unique") |
449 else |
450 else |
450 tab |
451 tab |
451 | NONE => Symtab.update (s, ((s, i), ty)) tab) |
452 | NONE => Symtab.update (s, ((s, i), ty)) tab) |
452 val vartab = collect_vars prop Symtab.empty |
453 val vartab = collect_vars prop Symtab.empty |
453 fun encodevar (s, t as (_, ty)) (encoding, tab) = |
454 fun encodevar (s, t as (_, ty)) (encoding, tab) = |
454 let |
455 let |
455 val (x, encoding) = Encode.insert (Var t) encoding |
456 val (x, encoding) = Encode.insert (Var t) encoding |
456 in |
457 in |
457 (encoding, Symtab.update (s, (x, ty)) tab) |
458 (encoding, Symtab.update (s, (x, ty)) tab) |
458 end |
459 end |
459 val (encoding, vartab) = Symtab.fold encodevar vartab (encoding, Symtab.empty) |
460 val (encoding, vartab) = Symtab.fold encodevar vartab (encoding, Symtab.empty) |
460 val varsubst = Inttab.make (map (fn (s, (x, _)) => (x, NONE)) (Symtab.dest vartab)) |
461 val varsubst = Inttab.make (map (fn (s, (x, _)) => (x, NONE)) (Symtab.dest vartab)) |
461 |
462 |
462 (* make the premises and the conclusion *) |
463 (* make the premises and the conclusion *) |
463 fun mk_prem encoding t = |
464 fun mk_prem encoding t = |
464 (let |
465 (let |
465 val (a, b) = Logic.dest_equals t |
466 val (a, b) = Logic.dest_equals t |
466 val ty = type_of a |
467 val ty = type_of a |
467 val (encoding, a) = remove_types encoding a |
468 val (encoding, a) = remove_types encoding a |
468 val (encoding, b) = remove_types encoding b |
469 val (encoding, b) = remove_types encoding b |
469 val (eq, encoding) = Encode.insert (Const ("==", ty --> ty --> @{typ "prop"})) encoding |
470 val (eq, encoding) = Encode.insert (Const ("==", ty --> ty --> @{typ "prop"})) encoding |
470 in |
471 in |
471 (encoding, EqPrem (a, b, ty, eq)) |
472 (encoding, EqPrem (a, b, ty, eq)) |
472 end handle TERM _ => let val (encoding, t) = remove_types encoding t in (encoding, Prem t) end) |
473 end handle TERM _ => let val (encoding, t) = remove_types encoding t in (encoding, Prem t) end) |
473 val (encoding, prems) = |
474 val (encoding, prems) = |
474 (fold_rev (fn t => fn (encoding, l) => |
475 (fold_rev (fn t => fn (encoding, l) => |
475 case mk_prem encoding t of |
476 case mk_prem encoding t of |
476 (encoding, t) => (encoding, t::l)) (Logic.strip_imp_prems prop) (encoding, [])) |
477 (encoding, t) => (encoding, t::l)) (Logic.strip_imp_prems prop) (encoding, [])) |
477 val (encoding, concl) = remove_types encoding (Logic.strip_imp_concl prop) |
478 val (encoding, concl) = remove_types encoding (Logic.strip_imp_concl prop) |
478 val _ = set_encoding computer encoding |
479 val _ = set_encoding computer encoding |
479 in |
480 in |
480 Theorem (Theory.check_thy (theory_of_thm th), stamp_of computer, vartab, varsubst, |
481 Theorem (Theory.check_thy (theory_of_thm th), stamp_of computer, vartab, varsubst, |
481 prems, concl, hyps, shyps) |
482 prems, concl, hyps, shyps) |
482 end |
483 end |
483 |
484 |
484 fun theory_of_theorem (Theorem (rthy,_,_,_,_,_,_,_)) = Theory.deref rthy |
485 fun theory_of_theorem (Theorem (rthy,_,_,_,_,_,_,_)) = Theory.deref rthy |
485 fun update_theory thy (Theorem (_,p0,p1,p2,p3,p4,p5,p6)) = |
486 fun update_theory thy (Theorem (_,p0,p1,p2,p3,p4,p5,p6)) = |
486 Theorem (Theory.check_thy thy,p0,p1,p2,p3,p4,p5,p6) |
487 Theorem (Theory.check_thy thy,p0,p1,p2,p3,p4,p5,p6) |
509 |
510 |
510 val vartab = vartab_of_theorem th |
511 val vartab = vartab_of_theorem th |
511 |
512 |
512 fun rewrite computer t = |
513 fun rewrite computer t = |
513 let |
514 let |
514 val naming = naming_of computer |
515 val naming = naming_of computer |
515 val (encoding, t) = remove_types (encoding_of computer) t |
516 val (encoding, t) = remove_types (encoding_of computer) t |
516 val t = runprog (prog_of computer) t |
517 val t = runprog (prog_of computer) t |
517 val _ = set_encoding computer encoding |
518 val _ = set_encoding computer encoding |
518 in |
519 in |
519 t |
520 t |
520 end |
521 end |
521 |
522 |
522 fun assert_varfree vs t = |
523 fun assert_varfree vs t = |
523 if AbstractMachine.forall_consts (fn x => Inttab.lookup vs x = NONE) t then |
524 if AbstractMachine.forall_consts (fn x => Inttab.lookup vs x = NONE) t then |
524 () |
525 () |
525 else |
526 else |
526 raise Compute "instantiate: assert_varfree failed" |
527 raise Compute "instantiate: assert_varfree failed" |
527 |
528 |
528 fun assert_closed t = |
529 fun assert_closed t = |
529 if AbstractMachine.closed t then |
530 if AbstractMachine.closed t then |
530 () |
531 () |
531 else |
532 else |
532 raise Compute "instantiate: not a closed term" |
533 raise Compute "instantiate: not a closed term" |
533 |
534 |
534 fun compute_inst (s, ct) vs = |
535 fun compute_inst (s, ct) vs = |
535 let |
536 let |
536 val _ = Theory.assert_super (theory_of_cterm ct) thy |
537 val _ = Theory.assert_super (theory_of_cterm ct) thy |
537 val ty = typ_of (ctyp_of_term ct) |
538 val ty = typ_of (ctyp_of_term ct) |
538 in |
539 in |
539 (case Symtab.lookup vartab s of |
540 (case Symtab.lookup vartab s of |
540 NONE => raise Compute ("instantiate: variable '"^s^"' not found in theorem") |
541 NONE => raise Compute ("instantiate: variable '"^s^"' not found in theorem") |
541 | SOME (x, ty') => |
542 | SOME (x, ty') => |
542 (case Inttab.lookup vs x of |
543 (case Inttab.lookup vs x of |
543 SOME (SOME _) => raise Compute ("instantiate: variable '"^s^"' has already been instantiated") |
544 SOME (SOME _) => raise Compute ("instantiate: variable '"^s^"' has already been instantiated") |
544 | SOME NONE => |
545 | SOME NONE => |
545 if ty <> ty' then |
546 if ty <> ty' then |
546 raise Compute ("instantiate: wrong type for variable '"^s^"'") |
547 raise Compute ("instantiate: wrong type for variable '"^s^"'") |
547 else |
548 else |
548 let |
549 let |
549 val t = rewrite computer (term_of ct) |
550 val t = rewrite computer (term_of ct) |
550 val _ = assert_varfree vs t |
551 val _ = assert_varfree vs t |
551 val _ = assert_closed t |
552 val _ = assert_closed t |
552 in |
553 in |
553 Inttab.update (x, SOME t) vs |
554 Inttab.update (x, SOME t) vs |
554 end |
555 end |
555 | NONE => raise Compute "instantiate: internal error")) |
556 | NONE => raise Compute "instantiate: internal error")) |
556 end |
557 end |
557 |
558 |
558 val vs = fold compute_inst insts (varsubst_of_theorem th) |
559 val vs = fold compute_inst insts (varsubst_of_theorem th) |
559 in |
560 in |
560 update_varsubst vs th |
561 update_varsubst vs th |
561 end |
562 end |
562 |
563 |
563 fun match_aterms subst = |
564 fun match_aterms subst = |
564 let |
565 let |
565 exception no_match |
566 exception no_match |
566 open AbstractMachine |
567 open AbstractMachine |
567 fun match subst (b as (Const c)) a = |
568 fun match subst (b as (Const c)) a = |
568 if a = b then subst |
569 if a = b then subst |
569 else |
570 else |
570 (case Inttab.lookup subst c of |
571 (case Inttab.lookup subst c of |
571 SOME (SOME a') => if a=a' then subst else raise no_match |
572 SOME (SOME a') => if a=a' then subst else raise no_match |
572 | SOME NONE => if AbstractMachine.closed a then |
573 | SOME NONE => if AbstractMachine.closed a then |
573 Inttab.update (c, SOME a) subst |
574 Inttab.update (c, SOME a) subst |
574 else raise no_match |
575 else raise no_match |
575 | NONE => raise no_match) |
576 | NONE => raise no_match) |
576 | match subst (b as (Var _)) a = if a=b then subst else raise no_match |
577 | match subst (b as (Var _)) a = if a=b then subst else raise no_match |
577 | match subst (App (u, v)) (App (u', v')) = match (match subst u u') v v' |
578 | match subst (App (u, v)) (App (u', v')) = match (match subst u u') v v' |
578 | match subst (Abs u) (Abs u') = match subst u u' |
579 | match subst (Abs u) (Abs u') = match subst u u' |
579 | match subst _ _ = raise no_match |
580 | match subst _ _ = raise no_match |
580 in |
581 in |
581 fn b => fn a => (SOME (match subst b a) handle no_match => NONE) |
582 fn b => fn a => (SOME (match subst b a) handle no_match => NONE) |
582 end |
583 end |
583 |
584 |
584 fun apply_subst vars_allowed subst = |
585 fun apply_subst vars_allowed subst = |
585 let |
586 let |
586 open AbstractMachine |
587 open AbstractMachine |
587 fun app (t as (Const c)) = |
588 fun app (t as (Const c)) = |
588 (case Inttab.lookup subst c of |
589 (case Inttab.lookup subst c of |
589 NONE => t |
590 NONE => t |
590 | SOME (SOME t) => Computed t |
591 | SOME (SOME t) => Computed t |
591 | SOME NONE => if vars_allowed then t else raise Compute "apply_subst: no vars allowed") |
592 | SOME NONE => if vars_allowed then t else raise Compute "apply_subst: no vars allowed") |
592 | app (t as (Var _)) = t |
593 | app (t as (Var _)) = t |
593 | app (App (u, v)) = App (app u, app v) |
594 | app (App (u, v)) = App (app u, app v) |
594 | app (Abs m) = Abs (app m) |
595 | app (Abs m) = Abs (app m) |
595 in |
596 in |
596 app |
597 app |
597 end |
598 end |
598 |
599 |
599 fun splicein n l L = List.take (L, n) @ l @ List.drop (L, n+1) |
600 fun splicein n l L = List.take (L, n) @ l @ List.drop (L, n+1) |
600 |
601 |
601 fun evaluate_prem computer prem_no th = |
602 fun evaluate_prem computer prem_no th = |
602 let |
603 let |
603 val _ = check_compatible computer th |
604 val _ = check_compatible computer th |
604 val prems = prems_of_theorem th |
605 val prems = prems_of_theorem th |
605 val varsubst = varsubst_of_theorem th |
606 val varsubst = varsubst_of_theorem th |
606 fun run vars_allowed t = |
607 fun run vars_allowed t = |
607 runprog (prog_of computer) (apply_subst vars_allowed varsubst t) |
608 runprog (prog_of computer) (apply_subst vars_allowed varsubst t) |
608 in |
609 in |
609 case List.nth (prems, prem_no) of |
610 case List.nth (prems, prem_no) of |
610 Prem _ => raise Compute "evaluate_prem: no equality premise" |
611 Prem _ => raise Compute "evaluate_prem: no equality premise" |
611 | EqPrem (a, b, ty, _) => |
612 | EqPrem (a, b, ty, _) => |
612 let |
613 let |
613 val a' = run false a |
614 val a' = run false a |
614 val b' = run true b |
615 val b' = run true b |
615 in |
616 in |
616 case match_aterms varsubst b' a' of |
617 case match_aterms varsubst b' a' of |
617 NONE => |
618 NONE => |
618 let |
619 let |
619 fun mk s = makestring (infer_types (naming_of computer) (encoding_of computer) ty s) |
620 fun mk s = makestring (infer_types (naming_of computer) (encoding_of computer) ty s) |
620 val left = "computed left side: "^(mk a') |
621 val left = "computed left side: "^(mk a') |
621 val right = "computed right side: "^(mk b') |
622 val right = "computed right side: "^(mk b') |
622 in |
623 in |
623 raise Compute ("evaluate_prem: cannot assign computed left to right hand side\n"^left^"\n"^right^"\n") |
624 raise Compute ("evaluate_prem: cannot assign computed left to right hand side\n"^left^"\n"^right^"\n") |
624 end |
625 end |
625 | SOME varsubst => |
626 | SOME varsubst => |
626 update_prems (splicein prem_no [] prems) (update_varsubst varsubst th) |
627 update_prems (splicein prem_no [] prems) (update_varsubst varsubst th) |
627 end |
628 end |
628 end |
629 end |
629 |
630 |
630 fun prem2term (Prem t) = t |
631 fun prem2term (Prem t) = t |
631 | prem2term (EqPrem (a,b,_,eq)) = |
632 | prem2term (EqPrem (a,b,_,eq)) = |
632 AbstractMachine.App (AbstractMachine.App (AbstractMachine.Const eq, a), b) |
633 AbstractMachine.App (AbstractMachine.App (AbstractMachine.Const eq, a), b) |
633 |
634 |
634 fun modus_ponens computer prem_no th' th = |
635 fun modus_ponens computer prem_no th' th = |
635 let |
636 let |
636 val _ = check_compatible computer th |
637 val _ = check_compatible computer th |
637 val thy = |
638 val thy = |
638 let |
639 let |
639 val thy1 = theory_of_theorem th |
640 val thy1 = theory_of_theorem th |
640 val thy2 = theory_of_thm th' |
641 val thy2 = theory_of_thm th' |
641 in |
642 in |
642 if Context.subthy (thy1, thy2) then thy2 |
643 if Context.subthy (thy1, thy2) then thy2 |
643 else if Context.subthy (thy2, thy1) then thy1 else |
644 else if Context.subthy (thy2, thy1) then thy1 else |
644 raise Compute "modus_ponens: theorems are not compatible with each other" |
645 raise Compute "modus_ponens: theorems are not compatible with each other" |
645 end |
646 end |
646 val th' = make_theorem computer th' [] |
647 val th' = make_theorem computer th' [] |
647 val varsubst = varsubst_of_theorem th |
648 val varsubst = varsubst_of_theorem th |
648 fun run vars_allowed t = |
649 fun run vars_allowed t = |
649 runprog (prog_of computer) (apply_subst vars_allowed varsubst t) |
650 runprog (prog_of computer) (apply_subst vars_allowed varsubst t) |
650 val prems = prems_of_theorem th |
651 val prems = prems_of_theorem th |
651 val prem = run true (prem2term (List.nth (prems, prem_no))) |
652 val prem = run true (prem2term (List.nth (prems, prem_no))) |
652 val concl = run false (concl_of_theorem th') |
653 val concl = run false (concl_of_theorem th') |
653 in |
654 in |
654 case match_aterms varsubst prem concl of |
655 case match_aterms varsubst prem concl of |
655 NONE => raise Compute "modus_ponens: conclusion does not match premise" |
656 NONE => raise Compute "modus_ponens: conclusion does not match premise" |
656 | SOME varsubst => |
657 | SOME varsubst => |
657 let |
658 let |
658 val th = update_varsubst varsubst th |
659 val th = update_varsubst varsubst th |
659 val th = update_prems (splicein prem_no (prems_of_theorem th') prems) th |
660 val th = update_prems (splicein prem_no (prems_of_theorem th') prems) th |
660 val th = update_hyps (merge_hyps (hyps_of_theorem th) (hyps_of_theorem th')) th |
661 val th = update_hyps (merge_hyps (hyps_of_theorem th) (hyps_of_theorem th')) th |
661 val th = update_shyps (merge_shyps (shyps_of_theorem th) (shyps_of_theorem th')) th |
662 val th = update_shyps (merge_shyps (shyps_of_theorem th) (shyps_of_theorem th')) th |
662 in |
663 in |
663 update_theory thy th |
664 update_theory thy th |
664 end |
665 end |
665 end |
666 end |
666 |
667 |
667 fun simplify computer th = |
668 fun simplify computer th = |
668 let |
669 let |
669 val _ = check_compatible computer th |
670 val _ = check_compatible computer th |