src/HOL/Tools/SMT/smt_translate.ML
changeset 42319 9a8ba59aed06
parent 41785 77dcc197df9a
child 42321 ce83c1654b86
equal deleted inserted replaced
42318:0fd33b6b22cf 42319:9a8ba59aed06
   166 
   166 
   167 
   167 
   168 (** eta-expand quantifiers, let expressions and built-ins *)
   168 (** eta-expand quantifiers, let expressions and built-ins *)
   169 
   169 
   170 local
   170 local
   171   fun eta T t = Abs (Name.uu, T, Term.incr_boundvars 1 t $ Bound 0)
   171   fun eta f T t = Abs (Name.uu, T, f (Term.incr_boundvars 1 t $ Bound 0))
   172 
   172 
   173   fun exp T = eta (Term.domain_type (Term.domain_type T))
   173   fun exp f T = eta f (Term.domain_type (Term.domain_type T))
   174 
   174 
   175   fun exp2 T q =
   175   fun exp2 T q =
   176     let val U = Term.domain_type T
   176     let val U = Term.domain_type T
   177     in Abs (Name.uu, U, q $ eta (Term.domain_type U) (Bound 0)) end
   177     in Abs (Name.uu, U, q $ eta I (Term.domain_type U) (Bound 0)) end
   178 
   178 
   179   fun exp2' T l =
   179   fun exp2' T l =
   180     let val (U1, U2) = Term.dest_funT T ||> Term.domain_type
   180     let val (U1, U2) = Term.dest_funT T ||> Term.domain_type
   181     in Abs (Name.uu, U1, eta U2 (l $ Bound 0)) end
   181     in Abs (Name.uu, U1, eta I U2 (l $ Bound 0)) end
   182 
   182 
   183   fun expf k i T t =
   183   fun expf k i T t =
   184     let val Ts = drop i (fst (SMT_Utils.dest_funT k T))
   184     let val Ts = drop i (fst (SMT_Utils.dest_funT k T))
   185     in
   185     in
   186       Term.incr_boundvars (length Ts) t
   186       Term.incr_boundvars (length Ts) t
   187       |> fold_index (fn (i, _) => fn u => u $ Bound i) Ts
   187       |> fold_index (fn (i, _) => fn u => u $ Bound i) Ts
   188       |> fold_rev (fn T => fn u => Abs (Name.uu, T, u)) Ts
   188       |> fold_rev (fn T => fn u => Abs (Name.uu, T, u)) Ts
   189     end
   189     end
   190 in
   190 in
   191 
   191 
   192 fun eta_expand ctxt funcs =
   192 fun eta_expand ctxt is_fol funcs =
   193   let
   193   let
   194     fun exp_func t T ts =
   194     fun exp_func t T ts =
   195       (case Termtab.lookup funcs t of
   195       (case Termtab.lookup funcs t of
   196         SOME k =>
   196         SOME k =>
   197           Term.list_comb (t, ts)
   197           Term.list_comb (t, ts)
   198           |> k <> length ts ? expf k (length ts) T
   198           |> k <> length ts ? expf k (length ts) T
   199       | NONE => Term.list_comb (t, ts))
   199       | NONE => Term.list_comb (t, ts))
   200 
   200 
   201     fun expand ((q as Const (@{const_name All}, _)) $ Abs a) = q $ abs_expand a
   201     fun expand ((q as Const (@{const_name All}, _)) $ Abs a) = q $ abs_expand a
   202       | expand ((q as Const (@{const_name All}, T)) $ t) = q $ exp T t
   202       | expand ((q as Const (@{const_name All}, T)) $ t) = q $ exp expand T t
   203       | expand (q as Const (@{const_name All}, T)) = exp2 T q
   203       | expand (q as Const (@{const_name All}, T)) = exp2 T q
   204       | expand ((q as Const (@{const_name Ex}, _)) $ Abs a) = q $ abs_expand a
   204       | expand ((q as Const (@{const_name Ex}, _)) $ Abs a) = q $ abs_expand a
   205       | expand ((q as Const (@{const_name Ex}, T)) $ t) = q $ exp T t
   205       | expand ((q as Const (@{const_name Ex}, T)) $ t) = q $ exp expand T t
   206       | expand (q as Const (@{const_name Ex}, T)) = exp2 T q
   206       | expand (q as Const (@{const_name Ex}, T)) = exp2 T q
   207       | expand ((l as Const (@{const_name Let}, _)) $ t $ Abs a) =
   207       | expand ((l as Const (@{const_name Let}, _)) $ t $ Abs a) =
   208           l $ expand t $ abs_expand a
   208           if is_fol then expand (Term.betapply (Abs a, t))
       
   209           else l $ expand t $ abs_expand a
   209       | expand ((l as Const (@{const_name Let}, T)) $ t $ u) =
   210       | expand ((l as Const (@{const_name Let}, T)) $ t $ u) =
   210           l $ expand t $ exp (Term.range_type T) u
   211           if is_fol then expand (u $ t)
       
   212           else l $ expand t $ exp expand (Term.range_type T) u
   211       | expand ((l as Const (@{const_name Let}, T)) $ t) =
   213       | expand ((l as Const (@{const_name Let}, T)) $ t) =
   212           exp2 T (l $ expand t)
   214           if is_fol then
   213       | expand (l as Const (@{const_name Let}, T)) = exp2' T l
   215             let val U = Term.domain_type (Term.range_type T)
       
   216             in Abs (Name.uu, U, Bound 0 $ Term.incr_boundvars 1 t) end
       
   217           else exp2 T (l $ expand t)
       
   218       | expand (l as Const (@{const_name Let}, T)) =
       
   219           if is_fol then 
       
   220             let val U = Term.domain_type (Term.range_type T)
       
   221             in
       
   222               Abs (Name.uu, Term.domain_type T, Abs (Name.uu, U,
       
   223                 Bound 0 $ Bound 1))
       
   224             end
       
   225           else exp2' T l
   214       | expand t =
   226       | expand t =
   215           (case Term.strip_comb t of
   227           (case Term.strip_comb t of
   216             (u as Const (c as (_, T)), ts) =>
   228             (u as Const (c as (_, T)), ts) =>
   217               (case SMT_Builtin.dest_builtin ctxt c ts of
   229               (case SMT_Builtin.dest_builtin ctxt c ts of
   218                 SOME (_, k, us, mk) =>
   230                 SOME (_, k, us, mk) =>
   361     mk_meta_eq @{thm SMT.term_true_def},
   373     mk_meta_eq @{thm SMT.term_true_def},
   362     mk_meta_eq @{thm SMT.term_false_def},
   374     mk_meta_eq @{thm SMT.term_false_def},
   363     @{lemma "P = True == P" by (rule eq_reflection) simp},
   375     @{lemma "P = True == P" by (rule eq_reflection) simp},
   364     @{lemma "if P then True else False == P" by (rule eq_reflection) simp}]
   376     @{lemma "if P then True else False == P" by (rule eq_reflection) simp}]
   365 
   377 
   366   fun reduce_let (Const (@{const_name Let}, _) $ t $ u) =
       
   367         reduce_let (Term.betapply (u, t))
       
   368     | reduce_let (t $ u) = reduce_let t $ reduce_let u
       
   369     | reduce_let (Abs (n, T, t)) = Abs (n, T, reduce_let t)
       
   370     | reduce_let t = t
       
   371 
       
   372   fun as_term t = @{const HOL.eq (bool)} $ t $ @{const SMT.term_true}
   378   fun as_term t = @{const HOL.eq (bool)} $ t $ @{const SMT.term_true}
   373 
   379 
   374   fun wrap_in_if t =
   380   fun wrap_in_if t =
   375     @{const If (bool)} $ t $ @{const SMT.term_true} $ @{const SMT.term_false}
   381     @{const If (bool)} $ t $ @{const SMT.term_true} $ @{const SMT.term_false}
   376 
   382 
   430               (case SMT_Builtin.dest_builtin_pred ctxt c ts of
   436               (case SMT_Builtin.dest_builtin_pred ctxt c ts of
   431                 SOME (_, _, us, mk) => mk (map in_term us)
   437                 SOME (_, _, us, mk) => mk (map in_term us)
   432               | NONE => as_term (in_term t)))
   438               | NONE => as_term (in_term t)))
   433       | _ => as_term (in_term t))
   439       | _ => as_term (in_term t))
   434   in
   440   in
   435     map (reduce_let #> in_form) #>
   441     map in_form #>
   436     cons (SMT_Utils.prop_of term_bool) #>
   442     cons (SMT_Utils.prop_of term_bool) #>
   437     pair (fol_rules, [term_bool], builtin)
   443     pair (fol_rules, [term_bool], builtin)
   438   end
   444   end
   439 
   445 
   440 end
   446 end
   564       ((make_tr_context prefixes, ctxt), ts1)
   570       ((make_tr_context prefixes, ctxt), ts1)
   565       |-> (if with_datatypes then collect_datatypes_and_records else no_dtyps)
   571       |-> (if with_datatypes then collect_datatypes_and_records else no_dtyps)
   566 
   572 
   567     val (ctxt2, ts3) =
   573     val (ctxt2, ts3) =
   568       ts2
   574       ts2
   569       |> eta_expand ctxt1 funcs
   575       |> eta_expand ctxt1 is_fol funcs
   570       |> lift_lambdas ctxt1
   576       |> lift_lambdas ctxt1
   571       ||> intro_explicit_application
   577       ||> intro_explicit_application
   572 
   578 
   573     val ((rewrite_rules, extra_thms, builtin), ts4) =
   579     val ((rewrite_rules, extra_thms, builtin), ts4) =
   574       (if is_fol then folify ctxt2 else pair ([], [], I)) ts3
   580       (if is_fol then folify ctxt2 else pair ([], [], I)) ts3