118 header = header, |
118 header = header, |
119 sorts = Typtab.fold (fn (_, (n, true)) => cons n | _ => I) typs [], |
119 sorts = Typtab.fold (fn (_, (n, true)) => cons n | _ => I) typs [], |
120 dtyps = dtyps, |
120 dtyps = dtyps, |
121 funcs = Termtab.fold (fn (_, (n, SOME ss)) => cons (n,ss) | _ => I) terms []} |
121 funcs = Termtab.fold (fn (_, (n, SOME ss)) => cons (n,ss) | _ => I) terms []} |
122 |
122 |
123 fun recon_of ctxt rules thms ithms revertT revert (_, _, typs, _, _, terms) = |
123 fun recon_of ctxt rules thms ithms (_, _, typs, _, _, terms) = |
124 let |
124 let |
125 fun add_typ (T, (n, _)) = Symtab.update (n, revertT T) |
125 fun add_typ (T, (n, _)) = Symtab.update (n, T) |
126 val typs' = Typtab.fold add_typ typs Symtab.empty |
126 val typs' = Typtab.fold add_typ typs Symtab.empty |
127 |
127 |
128 fun add_fun (t, (n, _)) = Symtab.update (n, revert t) |
128 fun add_fun (t, (n, _)) = Symtab.update (n, t) |
129 val terms' = Termtab.fold add_fun terms Symtab.empty |
129 val terms' = Termtab.fold add_fun terms Symtab.empty |
130 |
130 |
131 val assms = map (pair ~1) thms @ ithms |
131 val assms = map (pair ~1) thms @ ithms |
132 in |
132 in |
133 {context=ctxt, typs=typs', terms=terms', rewrite_rules=rules, assms=assms} |
133 {context=ctxt, typs=typs', terms=terms', rewrite_rules=rules, assms=assms} |
198 |
166 |
199 fun exp2' T l = |
167 fun exp2' T l = |
200 let val (U1, U2) = Term.dest_funT T ||> Term.domain_type |
168 let val (U1, U2) = Term.dest_funT T ||> Term.domain_type |
201 in Abs (Name.uu, U1, eta U2 (l $ Bound 0)) end |
169 in Abs (Name.uu, U1, eta U2 (l $ Bound 0)) end |
202 |
170 |
203 fun expf t i T ts = |
171 fun expf k i T t = |
204 let val Ts = U.dest_funT i T |> fst |> drop (length ts) |
172 let val Ts = drop i (fst (U.dest_funT k T)) |
205 in |
173 in |
206 Term.list_comb (t, ts) |
174 Term.incr_boundvars (length Ts) t |
207 |> Term.incr_boundvars (length Ts) |
|
208 |> fold_index (fn (i, _) => fn u => u $ Bound i) Ts |
175 |> fold_index (fn (i, _) => fn u => u $ Bound i) Ts |
209 |> fold_rev (fn T => fn u => Abs (Name.uu, T, u)) Ts |
176 |> fold_rev (fn T => fn u => Abs (Name.uu, T, u)) Ts |
210 end |
177 end |
211 |
|
212 fun expand ((q as Const (@{const_name All}, _)) $ Abs a) = q $ abs_expand a |
|
213 | expand ((q as Const (@{const_name All}, T)) $ t) = q $ exp T t |
|
214 | expand (q as Const (@{const_name All}, T)) = exp2 T q |
|
215 | expand ((q as Const (@{const_name Ex}, _)) $ Abs a) = q $ abs_expand a |
|
216 | expand ((q as Const (@{const_name Ex}, T)) $ t) = q $ exp T t |
|
217 | expand (q as Const (@{const_name Ex}, T)) = exp2 T q |
|
218 | expand ((l as Const (@{const_name Let}, _)) $ t $ Abs a) = |
|
219 l $ expand t $ abs_expand a |
|
220 | expand ((l as Const (@{const_name Let}, T)) $ t $ u) = |
|
221 l $ expand t $ exp (Term.range_type T) u |
|
222 | expand ((l as Const (@{const_name Let}, T)) $ t) = exp2 T (l $ expand t) |
|
223 | expand (l as Const (@{const_name Let}, T)) = exp2' T l |
|
224 | expand (Abs a) = abs_expand a |
|
225 | expand t = |
|
226 (case Term.strip_comb t of |
|
227 (u as Const (@{const_name If}, T), ts) => expf u 3 T (map expand ts) |
|
228 | (u as Var ((_, i), T), ts) => expf u i T (map expand ts) |
|
229 | (u, ts) => Term.list_comb (u, map expand ts)) |
|
230 |
|
231 and abs_expand (n, T, t) = Abs (n, T, expand t) |
|
232 in |
178 in |
233 |
179 |
234 val eta_expand = map expand |
180 fun eta_expand ctxt = |
|
181 let |
|
182 fun expand ((q as Const (@{const_name All}, _)) $ Abs a) = q $ abs_expand a |
|
183 | expand ((q as Const (@{const_name All}, T)) $ t) = q $ exp T t |
|
184 | expand (q as Const (@{const_name All}, T)) = exp2 T q |
|
185 | expand ((q as Const (@{const_name Ex}, _)) $ Abs a) = q $ abs_expand a |
|
186 | expand ((q as Const (@{const_name Ex}, T)) $ t) = q $ exp T t |
|
187 | expand (q as Const (@{const_name Ex}, T)) = exp2 T q |
|
188 | expand ((l as Const (@{const_name Let}, _)) $ t $ Abs a) = |
|
189 l $ expand t $ abs_expand a |
|
190 | expand ((l as Const (@{const_name Let}, T)) $ t $ u) = |
|
191 l $ expand t $ exp (Term.range_type T) u |
|
192 | expand ((l as Const (@{const_name Let}, T)) $ t) = |
|
193 exp2 T (l $ expand t) |
|
194 | expand (l as Const (@{const_name Let}, T)) = exp2' T l |
|
195 | expand t = |
|
196 (case Term.strip_comb t of |
|
197 (u as Const (c as (_, T)), ts) => |
|
198 (case B.dest_builtin ctxt c ts of |
|
199 SOME (_, k, us, mk) => |
|
200 if k = length us then mk (map expand us) |
|
201 else expf k (length ts) T (mk (map expand us)) |
|
202 | NONE => Term.list_comb (u, map expand ts)) |
|
203 | (Abs a, ts) => Term.list_comb (abs_expand a, map expand ts) |
|
204 | (u, ts) => Term.list_comb (u, map expand ts)) |
|
205 |
|
206 and abs_expand (n, T, t) = Abs (n, T, expand t) |
|
207 |
|
208 in map expand end |
235 |
209 |
236 end |
210 end |
237 |
211 |
238 |
212 |
239 (** lambda-lifting **) |
213 (** lambda-lifting **) |
352 end |
326 end |
353 |
327 |
354 |
328 |
355 (** map HOL formulas to FOL formulas (i.e., separate formulas froms terms) **) |
329 (** map HOL formulas to FOL formulas (i.e., separate formulas froms terms) **) |
356 |
330 |
357 val tboolT = @{typ SMT.term_bool} |
331 local |
358 val term_true = Const (@{const_name True}, tboolT) |
332 val term_bool = @{lemma "SMT.term_true ~= SMT.term_false" |
359 val term_false = Const (@{const_name False}, tboolT) |
333 by (simp add: SMT.term_true_def SMT.term_false_def)} |
360 |
334 |
361 val term_bool = @{lemma "True ~= False" by simp} |
335 val fol_rules = [ |
362 val term_bool_prop = |
336 Let_def, |
363 let |
337 mk_meta_eq @{thm SMT.term_true_def}, |
364 fun replace @{const HOL.eq (bool)} = @{const HOL.eq (SMT.term_bool)} |
338 mk_meta_eq @{thm SMT.term_false_def}, |
365 | replace @{const True} = term_true |
339 @{lemma "P = True == P" by (rule eq_reflection) simp}, |
366 | replace @{const False} = term_false |
340 @{lemma "if P then True else False == P" by (rule eq_reflection) simp}] |
367 | replace t = t |
341 |
368 in Term.map_aterms replace (U.prop_of term_bool) end |
342 fun reduce_let (Const (@{const_name Let}, _) $ t $ u) = |
369 |
343 reduce_let (Term.betapply (u, t)) |
370 val fol_rules = [ |
344 | reduce_let (t $ u) = reduce_let t $ reduce_let u |
371 Let_def, |
345 | reduce_let (Abs (n, T, t)) = Abs (n, T, reduce_let t) |
372 @{lemma "P = True == P" by (rule eq_reflection) simp}, |
346 | reduce_let t = t |
373 @{lemma "if P then True else False == P" by (rule eq_reflection) simp}] |
347 |
374 |
348 fun as_term t = @{const HOL.eq (bool)} $ t $ @{const SMT.term_true} |
375 fun reduce_let (Const (@{const_name Let}, _) $ t $ u) = |
349 |
376 reduce_let (Term.betapply (u, t)) |
350 fun wrap_in_if t = |
377 | reduce_let (t $ u) = reduce_let t $ reduce_let u |
351 @{const If (bool)} $ t $ @{const SMT.term_true} $ @{const SMT.term_false} |
378 | reduce_let (Abs (n, T, t)) = Abs (n, T, reduce_let t) |
352 |
379 | reduce_let t = t |
353 fun is_builtin_conn_or_pred ctxt c ts = |
380 |
354 is_some (B.dest_builtin_conn ctxt c ts) orelse |
381 fun is_pred_type NONE = false |
355 is_some (B.dest_builtin_pred ctxt c ts) |
382 | is_pred_type (SOME T) = (Term.body_type T = @{typ bool}) |
356 |
383 |
357 fun builtin b ctxt c ts = |
384 fun is_conn_type NONE = false |
358 (case (Const c, ts) of |
385 | is_conn_type (SOME T) = |
359 (@{const HOL.eq (bool)}, [t, u]) => |
386 forall (equal @{typ bool}) (Term.body_type T :: Term.binder_types T) |
360 if t = @{const SMT.term_true} orelse u = @{const SMT.term_true} then |
387 |
361 B.dest_builtin_eq ctxt t u |
388 fun revert_typ @{typ SMT.term_bool} = @{typ bool} |
362 else b ctxt c ts |
389 | revert_typ (Type (n, Ts)) = Type (n, map revert_typ Ts) |
363 | _ => b ctxt c ts) |
390 | revert_typ T = T |
364 in |
391 |
365 |
392 val revert_types = Term.map_types revert_typ |
366 fun folify ctxt = |
393 |
367 let |
394 fun folify ctxt builtins = |
|
395 let |
|
396 fun as_term t = @{const HOL.eq (SMT.term_bool)} $ t $ term_true |
|
397 |
|
398 fun as_tbool @{typ bool} = tboolT |
|
399 | as_tbool (Type (n, Ts)) = Type (n, map as_tbool Ts) |
|
400 | as_tbool T = T |
|
401 fun mapTs f g i = U.dest_funT i #> (fn (Ts, T) => map f Ts ---> g T) |
|
402 fun predT i = mapTs as_tbool I i |
|
403 fun funcT i = mapTs as_tbool as_tbool i |
|
404 fun func i (n, T) = (n, funcT i T) |
|
405 |
|
406 fun map_ifT T = T |> Term.dest_funT ||> funcT 2 |> (op -->) |
|
407 val if_term = @{const If (bool)} |> Term.dest_Const ||> map_ifT |> Const |
|
408 fun wrap_in_if t = if_term $ t $ term_true $ term_false |
|
409 |
|
410 fun in_list T f t = HOLogic.mk_list T (map f (HOLogic.dest_list t)) |
368 fun in_list T f t = HOLogic.mk_list T (map f (HOLogic.dest_list t)) |
411 |
369 |
412 fun in_term t = |
370 fun in_term t = |
413 (case Term.strip_comb t of |
371 (case Term.strip_comb t of |
414 (Const (n as @{const_name If}, T), [t1, t2, t3]) => |
372 (@{const True}, []) => @{const SMT.term_true} |
415 Const (n, map_ifT T) $ in_form t1 $ in_term t2 $ in_term t3 |
373 | (@{const False}, []) => @{const SMT.term_false} |
416 | (Const (@{const_name HOL.eq}, _), _) => wrap_in_if (in_form t) |
374 | (u as Const (@{const_name If}, _), [t1, t2, t3]) => |
417 | (Var (ni as (_, i), T), ts) => |
375 u $ in_form t1 $ in_term t2 $ in_term t3 |
418 let val U = Vartab.lookup builtins ni |
|
419 in |
|
420 if is_conn_type U orelse is_pred_type U then wrap_in_if (in_form t) |
|
421 else Term.list_comb (Var (ni, funcT i T), map in_term ts) |
|
422 end |
|
423 | (Const c, ts) => |
376 | (Const c, ts) => |
424 Term.list_comb (Const (func (length ts) c), map in_term ts) |
377 if is_builtin_conn_or_pred ctxt c ts then wrap_in_if (in_form t) |
425 | (Free c, ts) => |
378 else Term.list_comb (Const c, map in_term ts) |
426 Term.list_comb (Free (func (length ts) c), map in_term ts) |
379 | (Free c, ts) => Term.list_comb (Free c, map in_term ts) |
427 | _ => t) |
380 | _ => t) |
428 |
381 |
429 and in_weight ((c as @{const SMT.weight}) $ w $ t) = c $ w $ in_form t |
382 and in_weight ((c as @{const SMT.weight}) $ w $ t) = c $ w $ in_form t |
430 | in_weight t = in_form t |
383 | in_weight t = in_form t |
431 |
384 |
432 and in_pat (Const (c as (@{const_name SMT.pat}, _)) $ t) = |
385 and in_pat ((p as Const (@{const_name SMT.pat}, _)) $ t) = p $ in_term t |
433 Const (func 1 c) $ in_term t |
386 | in_pat ((p as Const (@{const_name SMT.nopat}, _)) $ t) = p $ in_term t |
434 | in_pat (Const (c as (@{const_name SMT.nopat}, _)) $ t) = |
|
435 Const (func 1 c) $ in_term t |
|
436 | in_pat t = raise TERM ("bad pattern", [t]) |
387 | in_pat t = raise TERM ("bad pattern", [t]) |
437 |
388 |
438 and in_pats ps = |
389 and in_pats ps = |
439 in_list @{typ "SMT.pattern list"} (in_list @{typ SMT.pattern} in_pat) ps |
390 in_list @{typ "SMT.pattern list"} (in_list @{typ SMT.pattern} in_pat) ps |
440 |
391 |
441 and in_trig ((c as @{const SMT.trigger}) $ p $ t) = |
392 and in_trigger ((c as @{const SMT.trigger}) $ p $ t) = |
442 c $ in_pats p $ in_weight t |
393 c $ in_pats p $ in_weight t |
443 | in_trig t = in_weight t |
394 | in_trigger t = in_weight t |
444 |
395 |
445 and in_form t = |
396 and in_form t = |
446 (case Term.strip_comb t of |
397 (case Term.strip_comb t of |
447 (q as Const (qn, _), [Abs (n, T, u)]) => |
398 (q as Const (qn, _), [Abs (n, T, u)]) => |
448 if member (op =) [@{const_name All}, @{const_name Ex}] qn then |
399 if member (op =) [@{const_name All}, @{const_name Ex}] qn then |
449 q $ Abs (n, as_tbool T, in_trig u) |
400 q $ Abs (n, T, in_trigger u) |
450 else as_term (in_term t) |
401 else as_term (in_term t) |
451 | (u as Const (@{const_name If}, _), ts) => |
402 | (Const c, ts) => |
452 Term.list_comb (u, map in_form ts) |
403 (case B.dest_builtin_conn ctxt c ts of |
453 | (b as @{const HOL.eq (bool)}, ts) => Term.list_comb (b, map in_form ts) |
404 SOME (_, _, us, mk) => mk (map in_form us) |
454 | (Const (n as @{const_name HOL.eq}, T), ts) => |
405 | NONE => |
455 Term.list_comb (Const (n, predT 2 T), map in_term ts) |
406 (case B.dest_builtin_pred ctxt c ts of |
456 | (b as Var (ni as (_, i), T), ts) => |
407 SOME (_, _, us, mk) => mk (map in_term us) |
457 if is_conn_type (Vartab.lookup builtins ni) then |
408 | NONE => as_term (in_term t))) |
458 Term.list_comb (b, map in_form ts) |
|
459 else if is_pred_type (Vartab.lookup builtins ni) then |
|
460 Term.list_comb (Var (ni, predT i T), map in_term ts) |
|
461 else as_term (in_term t) |
|
462 | _ => as_term (in_term t)) |
409 | _ => as_term (in_term t)) |
463 in |
410 in |
464 map (reduce_let #> in_form) #> |
411 map (reduce_let #> in_form) #> |
465 cons (mark_builtins' ctxt term_bool_prop) #> |
412 cons (U.prop_of term_bool) #> |
466 pair (fol_rules, [term_bool]) |
413 pair (fol_rules, [term_bool], builtin) |
467 end |
414 end |
468 |
415 |
|
416 end |
469 |
417 |
470 |
418 |
471 (* translation into intermediate format *) |
419 (* translation into intermediate format *) |
472 |
420 |
473 (** utility functions **) |
421 (** utility functions **) |
535 trans b #>> (fn ((Ts', ps'), b') => SQua (q, Ts', ps', w, b')) |
481 trans b #>> (fn ((Ts', ps'), b') => SQua (q, Ts', ps', w, b')) |
536 | NONE => raise TERM ("unsupported quantifier", [t])) |
482 | NONE => raise TERM ("unsupported quantifier", [t])) |
537 | (Const (@{const_name Let}, _), [t1, Abs (_, T, t2)]) => |
483 | (Const (@{const_name Let}, _), [t1, Abs (_, T, t2)]) => |
538 transT T ##>> trans t1 ##>> trans t2 #>> |
484 transT T ##>> trans t1 ##>> trans t2 #>> |
539 (fn ((U, u1), u2) => SLet (U, u1, u2)) |
485 (fn ((U, u1), u2) => SLet (U, u1, u2)) |
540 | (Var ((n, _), _), ts) => fold_map trans ts #>> app n |
486 | (u as Const (c as (_, T)), ts) => |
541 | (u as Const (c as (n, T)), ts) => |
487 (case builtin ctxt c ts of |
542 if member (op =) unmarked_builtins n then |
488 SOME (n, _, us, _) => fold_map trans us #>> app n |
543 (case B.builtin_fun ctxt c ts of |
489 | NONE => transs u T ts) |
544 SOME (((m, _), _), us, _) => fold_map trans us #>> app m |
|
545 | NONE => raise TERM ("not a built-in symbol", [t])) |
|
546 else transs u T ts |
|
547 | (u as Free (_, T), ts) => transs u T ts |
490 | (u as Free (_, T), ts) => transs u T ts |
548 | (Bound i, []) => pair (SVar i) |
491 | (Bound i, []) => pair (SVar i) |
549 | _ => raise TERM ("bad SMT term", [t])) |
492 | _ => raise TERM ("bad SMT term", [t])) |
550 |
493 |
551 and transs t T ts = |
494 and transs t T ts = |
588 val with_datatypes = |
531 val with_datatypes = |
589 has_datatypes andalso Config.get ctxt SMT_Config.datatypes |
532 has_datatypes andalso Config.get ctxt SMT_Config.datatypes |
590 |
533 |
591 fun no_dtyps (tr_context, ctxt) ts = (([], tr_context, ctxt), ts) |
534 fun no_dtyps (tr_context, ctxt) ts = (([], tr_context, ctxt), ts) |
592 |
535 |
593 val (builtins, ts1) = |
536 val ts1 = map (Envir.beta_eta_contract o U.prop_of o snd) ithms |
594 ithms |
|
595 |> map (Envir.beta_eta_contract o U.prop_of o snd) |
|
596 |> mark_builtins ctxt |
|
597 |
537 |
598 val ((dtyps, tr_context, ctxt1), ts2) = |
538 val ((dtyps, tr_context, ctxt1), ts2) = |
599 ((make_tr_context prefixes, ctxt), ts1) |
539 ((make_tr_context prefixes, ctxt), ts1) |
600 |-> (if with_datatypes then collect_datatypes_and_records else no_dtyps) |
540 |-> (if with_datatypes then collect_datatypes_and_records else no_dtyps) |
601 |
541 |
602 val (ctxt2, ts3) = |
542 val (ctxt2, ts3) = |
603 ts2 |
543 ts2 |
604 |> eta_expand |
544 |> eta_expand ctxt1 |
605 |> lift_lambdas ctxt1 |
545 |> lift_lambdas ctxt1 |
606 ||> intro_explicit_application |
546 ||> intro_explicit_application |
607 |
547 |
608 val ((rewrite_rules, extra_thms), ts4) = |
548 val ((rewrite_rules, extra_thms, builtin), ts4) = |
609 (if is_fol then folify ctxt2 builtins else pair ([], [])) ts3 |
549 (if is_fol then folify ctxt2 else pair ([], [], I)) ts3 |
610 |
550 |
611 val rewrite_rules' = fun_app_eq :: rewrite_rules |
551 val rewrite_rules' = fun_app_eq :: rewrite_rules |
612 in |
552 in |
613 (ts4, tr_context) |
553 (ts4, tr_context) |
614 |-> intermediate header dtyps ctxt2 |
554 |-> intermediate header dtyps (builtin B.dest_builtin) ctxt2 |
615 |>> uncurry (serialize comments) |
555 |>> uncurry (serialize comments) |
616 ||> recon_of ctxt2 rewrite_rules' extra_thms ithms revert_typ revert_types |
556 ||> recon_of ctxt2 rewrite_rules' extra_thms ithms |
617 end |
557 end |
618 |
558 |
619 end |
559 end |