src/HOL/Tools/Predicate_Compile/predicate_compile_core.ML
changeset 32668 b2de45007537
parent 32667 09546e654222
child 32669 462b1dd67a58
equal deleted inserted replaced
32667:09546e654222 32668:b2de45007537
     4 to equations.
     4 to equations.
     5 *)
     5 *)
     6 
     6 
     7 signature PREDICATE_COMPILE_CORE =
     7 signature PREDICATE_COMPILE_CORE =
     8 sig
     8 sig
       
     9   val setup: theory -> theory
       
    10   val code_pred: bool -> string -> Proof.context -> Proof.state
       
    11   val code_pred_cmd: bool -> string -> Proof.context -> Proof.state
     9   type smode = (int * int list option) list
    12   type smode = (int * int list option) list
    10   type mode = smode option list * smode
    13   type mode = smode option list * smode
    11   datatype tmode = Mode of mode * smode * tmode option list;
    14   datatype tmode = Mode of mode * smode * tmode option list;
    12   (*val add_equations_of: bool -> string list -> theory -> theory *)
    15   (*val add_equations_of: bool -> string list -> theory -> theory *)
    13   val register_predicate : (thm list * thm * int) -> theory -> theory
    16   val register_predicate : (thm list * thm * int) -> theory -> theory
       
    17   val register_intros : thm list -> theory -> theory
    14   val is_registered : theory -> string -> bool
    18   val is_registered : theory -> string -> bool
    15  (* val fetch_pred_data : theory -> string -> (thm list * thm * int)  *)
    19  (* val fetch_pred_data : theory -> string -> (thm list * thm * int)  *)
    16   val predfun_intro_of: theory -> string -> mode -> thm
    20   val predfun_intro_of: theory -> string -> mode -> thm
    17   val predfun_elim_of: theory -> string -> mode -> thm
    21   val predfun_elim_of: theory -> string -> mode -> thm
    18   val strip_intro_concl: int -> term -> term * (term list * term list)
    22   val strip_intro_concl: int -> term -> term * (term list * term list)
    22   val string_of_mode : mode -> string
    26   val string_of_mode : mode -> string
    23   val intros_of: theory -> string -> thm list
    27   val intros_of: theory -> string -> thm list
    24   val nparams_of: theory -> string -> int
    28   val nparams_of: theory -> string -> int
    25   val add_intro: thm -> theory -> theory
    29   val add_intro: thm -> theory -> theory
    26   val set_elim: thm -> theory -> theory
    30   val set_elim: thm -> theory -> theory
    27   val setup: theory -> theory
    31   val set_nparams : string -> int -> theory -> theory
    28   val code_pred: string -> Proof.context -> Proof.state
       
    29   val code_pred_cmd: string -> Proof.context -> Proof.state
       
    30   val print_stored_rules: theory -> unit
    32   val print_stored_rules: theory -> unit
    31   val print_all_modes: theory -> unit
    33   val print_all_modes: theory -> unit
    32   val do_proofs: bool ref
    34   val do_proofs: bool ref
    33   val mk_casesrule : Proof.context -> int -> thm list -> term
    35   val mk_casesrule : Proof.context -> int -> thm list -> term
    34   val analyze_compr: theory -> term -> term
    36   val analyze_compr: theory -> term -> term
   104 end;
   106 end;
   105 
   107 
   106 structure Predicate_Compile_Core : PREDICATE_COMPILE_CORE =
   108 structure Predicate_Compile_Core : PREDICATE_COMPILE_CORE =
   107 struct
   109 struct
   108 
   110 
       
   111 open Predicate_Compile_Aux;
   109 (** auxiliary **)
   112 (** auxiliary **)
   110 
   113 
   111 (* debug stuff *)
   114 (* debug stuff *)
   112 
   115 
   113 fun tracing s = (if ! Toplevel.debug then Output.tracing s else ());
   116 fun tracing s = (if ! Toplevel.debug then Output.tracing s else ());
   185   val (params, args) = chop nparams all_args
   188   val (params, args) = chop nparams all_args
   186 in (pred, (params, args)) end
   189 in (pred, (params, args)) end
   187 
   190 
   188 (** data structures **)
   191 (** data structures **)
   189 
   192 
   190 type smode = (int * int list option) list;
   193 type smode = (int * int list option) list
   191 type mode = smode option list * smode;
   194 type mode = smode option list * smode;
   192 datatype tmode = Mode of mode * smode * tmode option list;
   195 datatype tmode = Mode of mode * smode * tmode option list;
   193 
   196 
   194 fun gen_split_smode (mk_tuple, strip_tuple) smode ts =
   197 fun gen_split_smode (mk_tuple, strip_tuple) smode ts =
   195   let
   198   let
   236 
   239 
   237 fun string_of_tmode (Mode (predmode, termmode, param_modes)) =
   240 fun string_of_tmode (Mode (predmode, termmode, param_modes)) =
   238   "predmode: " ^ (string_of_mode predmode) ^ 
   241   "predmode: " ^ (string_of_mode predmode) ^ 
   239   (if null param_modes then "" else
   242   (if null param_modes then "" else
   240     "; " ^ "params: " ^ commas (map (the_default "NONE" o Option.map string_of_tmode) param_modes))
   243     "; " ^ "params: " ^ commas (map (the_default "NONE" o Option.map string_of_tmode) param_modes))
       
   244 
       
   245 (* generation of case rules from user-given introduction rules *)
       
   246 
       
   247 fun mk_casesrule ctxt nparams introrules =
       
   248   let
       
   249     val intros = map (Logic.unvarify o prop_of) introrules
       
   250     val (pred, (params, args)) = strip_intro_concl nparams (hd intros)
       
   251     val ([propname], ctxt1) = Variable.variant_fixes ["thesis"] ctxt
       
   252     val prop = HOLogic.mk_Trueprop (Free (propname, HOLogic.boolT))
       
   253     val (argnames, ctxt2) = Variable.variant_fixes
       
   254       (map (fn i => "a" ^ string_of_int i) (1 upto (length args))) ctxt1
       
   255     val argvs = map2 (curry Free) argnames (map fastype_of args)
       
   256     fun mk_case intro =
       
   257       let
       
   258         val (_, (_, args)) = strip_intro_concl nparams intro
       
   259         val prems = Logic.strip_imp_prems intro
       
   260         val eqprems = map (HOLogic.mk_Trueprop o HOLogic.mk_eq) (argvs ~~ args)
       
   261         val frees = (fold o fold_aterms)
       
   262           (fn t as Free _ =>
       
   263               if member (op aconv) params t then I else insert (op aconv) t
       
   264            | _ => I) (args @ prems) []
       
   265       in fold Logic.all frees (Logic.list_implies (eqprems @ prems, prop)) end
       
   266     val assm = HOLogic.mk_Trueprop (list_comb (pred, params @ argvs))
       
   267     val cases = map mk_case intros
       
   268   in Logic.list_implies (assm :: cases, prop) end;
   241     
   269     
       
   270 
   242 datatype indprem = Prem of term list * term | Negprem of term list * term | Sidecond of term |
   271 datatype indprem = Prem of term list * term | Negprem of term list * term | Sidecond of term |
   243   GeneratorPrem of term list * term | Generator of (string * typ);
   272   GeneratorPrem of term list * term | Generator of (string * typ);
   244 
   273 
   245 type moded_clause = term list * (indprem * tmode) list
   274 type moded_clause = term list * (indprem * tmode) list
   246 type 'a pred_mode_table = (string * (mode * 'a) list) list
   275 type 'a pred_mode_table = (string * (mode * 'a) list) list
   577   let
   606   let
   578     fun find is n [] = is
   607     fun find is n [] = is
   579       | find is n (x :: xs) = find (if pred x then (n :: is) else is) (n + 1) xs;
   608       | find is n (x :: xs) = find (if pred x then (n :: is) else is) (n + 1) xs;
   580   in rev (find [] 0 xs) end;
   609   in rev (find [] 0 xs) end;
   581 
   610 
   582 fun is_predT (T as Type("fun", [_, _])) = (snd (strip_type T) = HOLogic.boolT)
       
   583   | is_predT _ = false
       
   584   
       
   585 fun guess_nparams T =
   611 fun guess_nparams T =
   586   let
   612   let
   587     val argTs = binder_types T
   613     val argTs = binder_types T
   588     val nparams = fold (curry Int.max)
   614     val nparams = fold (curry Int.max)
   589       (map (fn x => x + 1) (find_indexes is_predT argTs)) 0
   615       (map (fn x => x + 1) (find_indexes is_predT argTs)) 0
   609 
   635 
   610 fun set_nparams name nparams = let
   636 fun set_nparams name nparams = let
   611     fun set (intros, elim, _ ) = (intros, elim, nparams) 
   637     fun set (intros, elim, _ ) = (intros, elim, nparams) 
   612   in PredData.map (Graph.map_node name (map_pred_data (apfst set))) end
   638   in PredData.map (Graph.map_node name (map_pred_data (apfst set))) end
   613     
   639     
   614 fun register_predicate (pre_intros, pre_elim, nparams) thy = let
   640 fun register_predicate (pre_intros, pre_elim, nparams) thy =
       
   641   let
   615     val (name, _) = dest_Const (fst (strip_intro_concl nparams (prop_of (hd pre_intros))))
   642     val (name, _) = dest_Const (fst (strip_intro_concl nparams (prop_of (hd pre_intros))))
   616     (* preprocessing *)
   643     (* preprocessing *)
   617     val intros = ind_set_codegen_preproc thy (map (preprocess_intro thy) pre_intros)
   644     val intros = ind_set_codegen_preproc thy (map (preprocess_intro thy) pre_intros)
   618     val elim = singleton (ind_set_codegen_preproc thy) (preprocess_elim thy nparams pre_elim)
   645     val elim = singleton (ind_set_codegen_preproc thy) (preprocess_elim thy nparams pre_elim)
   619   in
   646   in
   620     PredData.map
   647     if not (member (op =) (Graph.keys (PredData.get thy)) name) then
       
   648       PredData.map
   621       (Graph.new_node (name, mk_pred_data ((intros, SOME elim, nparams), ([], [], [])))) thy
   649       (Graph.new_node (name, mk_pred_data ((intros, SOME elim, nparams), ([], [], [])))) thy
       
   650     else thy
   622   end
   651   end
       
   652 
       
   653 fun register_intros pre_intros thy =
       
   654   let
       
   655   val (_, T) = dest_Const (fst (strip_intro_concl 0 (prop_of (hd pre_intros))))
       
   656   val nparams = guess_nparams T
       
   657   val pre_elim = 
       
   658     (Drule.standard o (setmp quick_and_dirty true (SkipProof.make_thm thy)))
       
   659     (mk_casesrule (ProofContext.init thy) nparams pre_intros)
       
   660   in register_predicate (pre_intros, pre_elim, nparams) thy end
   623 
   661 
   624 fun set_generator_name pred mode name = 
   662 fun set_generator_name pred mode name = 
   625   let
   663   let
   626     val set = (apsnd o apsnd3 o cons) (mode, mk_function_data (name, NONE))
   664     val set = (apsnd o apsnd3 o cons) (mode, mk_function_data (name, NONE))
   627   in
   665   in
   862 fun subsets i j = if i <= j then
   900 fun subsets i j = if i <= j then
   863        let val is = subsets (i+1) j
   901        let val is = subsets (i+1) j
   864        in merge (map (fn ks => i::ks) is) is end
   902        in merge (map (fn ks => i::ks) is) is end
   865      else [[]];
   903      else [[]];
   866      
   904      
   867 (* FIXME: should be in library - map_prod *)
   905 (* FIXME: should be in library - cprod = map_prod I *)
   868 fun cprod ([], ys) = []
   906 fun cprod ([], ys) = []
   869   | cprod (x :: xs, ys) = map (pair x) ys @ cprod (xs, ys);
   907   | cprod (x :: xs, ys) = map (pair x) ys @ cprod (xs, ys);
   870 
   908 
   871 fun cprods xss = foldr (map op :: o cprod) [[]] xss;
   909 fun cprods xss = foldr (map op :: o cprod) [[]] xss;
   872 
   910 
   984     val T = the (AList.lookup (op =) vTs v)
  1022     val T = the (AList.lookup (op =) vTs v)
   985   in
  1023   in
   986     (Generator (v, T), Mode (([], []), [], []))
  1024     (Generator (v, T), Mode (([], []), [], []))
   987   end;
  1025   end;
   988 
  1026 
   989 fun gen_prem (Prem (us, t)) = GeneratorPrem (us, t) 
  1027 fun gen_prem (Prem (us, t)) = GeneratorPrem (us, t)
       
  1028   | gen_prem (Negprem (us, t)) = error "it is a negated prem"
       
  1029   | gen_prem (Sidecond t) = error "it is a sidecond"
   990   | gen_prem _ = error "gen_prem : invalid input for gen_prem"
  1030   | gen_prem _ = error "gen_prem : invalid input for gen_prem"
   991 
  1031 
   992 fun param_gen_prem param_vs (p as Prem (us, t as Free (v, _))) =
  1032 fun param_gen_prem param_vs (p as Prem (us, t as Free (v, _))) =
   993   if member (op =) param_vs v then
  1033   if member (op =) param_vs v then
   994     GeneratorPrem (us, t)
  1034     GeneratorPrem (us, t)
   995   else p  
  1035   else p  
   996   | param_gen_prem param_vs p = p
  1036   | param_gen_prem param_vs p = p
   997   
  1037   
   998 fun check_mode_clause with_generator thy param_vs modes gen_modes (iss, is) (ts, ps) =
  1038 fun check_mode_clause with_generator thy param_vs modes gen_modes (iss, is) (ts, ps) =
   999   let
  1039   let
       
  1040     (*
       
  1041   val _ = Output.tracing ("param_vs:" ^ commas param_vs)
       
  1042   val _ = Output.tracing ("iss:" ^
       
  1043     commas (map (fn is => case is of SOME is => string_of_smode is | NONE => "NONE") iss))
       
  1044     *)
  1000     val modes' = modes @ List.mapPartial
  1045     val modes' = modes @ List.mapPartial
  1001       (fn (_, NONE) => NONE | (v, SOME js) => SOME (v, [([], js)]))
  1046       (fn (_, NONE) => NONE | (v, SOME js) => SOME (v, [([], js)]))
  1002         (param_vs ~~ iss);
  1047         (param_vs ~~ iss);
  1003     val gen_modes' = gen_modes @ List.mapPartial
  1048     val gen_modes' = gen_modes @ List.mapPartial
  1004       (fn (_, NONE) => NONE | (v, SOME js) => SOME (v, [([], js)]))
  1049       (fn (_, NONE) => NONE | (v, SOME js) => SOME (v, [([], js)]))
  1008     fun check_mode_prems acc_ps vs [] = SOME (acc_ps, vs)
  1053     fun check_mode_prems acc_ps vs [] = SOME (acc_ps, vs)
  1009       | check_mode_prems acc_ps vs ps = (case select_mode_prem thy modes' vs ps of
  1054       | check_mode_prems acc_ps vs ps = (case select_mode_prem thy modes' vs ps of
  1010           NONE =>
  1055           NONE =>
  1011             (if with_generator then
  1056             (if with_generator then
  1012               (case select_mode_prem thy gen_modes' vs ps of
  1057               (case select_mode_prem thy gen_modes' vs ps of
  1013                   SOME (p, SOME mode) => check_mode_prems ((gen_prem p, mode) :: acc_ps) 
  1058                 SOME (p as Prem _, SOME mode) => check_mode_prems ((gen_prem p, mode) :: acc_ps) 
  1014                   (case p of Prem (us, _) => vs union terms_vs us | _ => vs)
  1059                   (case p of Prem (us, _) => vs union terms_vs us | _ => vs)
  1015                   (filter_out (equal p) ps)
  1060                   (filter_out (equal p) ps)
  1016                 | NONE =>
  1061                 | NONE =>
  1017                   let 
  1062                   let 
  1018                     val all_generator_vs = all_subsets (prem_vs \\ vs) |> sort (int_ord o (pairself length))
  1063                     val all_generator_vs = all_subsets (prem_vs \\ vs) |> sort (int_ord o (pairself length))
  1019                   in
  1064                   in
  1020                     case (find_first (fn generator_vs => is_some
  1065                     case (find_first (fn generator_vs => is_some
  1021                       (select_mode_prem thy modes' (vs union generator_vs) ps)) all_generator_vs) of
  1066                       (select_mode_prem thy modes' (vs union generator_vs) ps)) all_generator_vs) of
  1022                       SOME generator_vs => check_mode_prems ((map (generator vTs) generator_vs) @ acc_ps)
  1067                       SOME generator_vs => check_mode_prems ((map (generator vTs) generator_vs) @ acc_ps)
  1023                         (vs union generator_vs) ps
  1068                         (vs union generator_vs) ps
  1024                     | NONE => NONE
  1069                     | NONE => let
       
  1070                     val _ = Output.tracing ("ps:" ^ (commas
       
  1071                     (map (fn p => string_of_moded_prem thy (p, Mode (([], []), [], []))) ps)))
       
  1072                       in error "mode analysis failed" end
  1025                   end)
  1073                   end)
  1026             else
  1074             else
  1027               NONE)
  1075               NONE)
  1028         | SOME (p, SOME mode) => check_mode_prems ((if with_generator then param_gen_prem param_vs p else p, mode) :: acc_ps) 
  1076         | SOME (p, SOME mode) => check_mode_prems ((if with_generator then param_gen_prem param_vs p else p, mode) :: acc_ps) 
  1029             (case p of Prem (us, _) => vs union terms_vs us | _ => vs)
  1077             (case p of Prem (us, _) => vs union terms_vs us | _ => vs)
  1491   val unfolddef_tac = Simplifier.asm_full_simp_tac (HOL_basic_ss addsimps simprules) 1
  1539   val unfolddef_tac = Simplifier.asm_full_simp_tac (HOL_basic_ss addsimps simprules) 1
  1492   val introthm = Goal.prove (ProofContext.init thy) (argnames @ param_names @ param_names' @ ["y"]) [] introtrm (fn {...} => unfolddef_tac)
  1540   val introthm = Goal.prove (ProofContext.init thy) (argnames @ param_names @ param_names' @ ["y"]) [] introtrm (fn {...} => unfolddef_tac)
  1493   val P = HOLogic.mk_Trueprop (Free ("P", HOLogic.boolT));
  1541   val P = HOLogic.mk_Trueprop (Free ("P", HOLogic.boolT));
  1494   val elimtrm = Logic.list_implies ([funpropE, Logic.mk_implies (predpropE, P)], P)
  1542   val elimtrm = Logic.list_implies ([funpropE, Logic.mk_implies (predpropE, P)], P)
  1495   val elimthm = Goal.prove (ProofContext.init thy) (argnames @ param_names @ param_names' @ ["y", "P"]) [] elimtrm (fn {...} => unfolddef_tac)
  1543   val elimthm = Goal.prove (ProofContext.init thy) (argnames @ param_names @ param_names' @ ["y", "P"]) [] elimtrm (fn {...} => unfolddef_tac)
  1496 	val _ = Output.tracing (Display.string_of_thm_global thy elimthm)
       
  1497 	val _ = Output.tracing (Display.string_of_thm_global thy introthm)
       
  1498 
       
  1499 in
  1544 in
  1500   (introthm, elimthm)
  1545   (introthm, elimthm)
  1501 end;
  1546 end;
  1502 
  1547 
  1503 fun create_constname_of_mode thy prefix name mode = 
  1548 fun create_constname_of_mode thy prefix name mode = 
  1607         end;
  1652         end;
  1608       val predterm = PredicateCompFuns.mk_Enum (mk_split_lambda xouts
  1653       val predterm = PredicateCompFuns.mk_Enum (mk_split_lambda xouts
  1609         (list_comb (Const (name, T), xparams' @ xargs)))
  1654         (list_comb (Const (name, T), xparams' @ xargs)))
  1610       val lhs = list_comb (Const (mode_cname, funT), xparams @ xins)
  1655       val lhs = list_comb (Const (mode_cname, funT), xparams @ xins)
  1611       val def = Logic.mk_equals (lhs, predterm)
  1656       val def = Logic.mk_equals (lhs, predterm)
  1612 			val _ = Output.tracing ("def:" ^ (Syntax.string_of_term_global thy def))
       
  1613       val ([definition], thy') = thy |>
  1657       val ([definition], thy') = thy |>
  1614         Sign.add_consts_i [(Binding.name mode_cbasename, funT, NoSyn)] |>
  1658         Sign.add_consts_i [(Binding.name mode_cbasename, funT, NoSyn)] |>
  1615         PureThy.add_defs false [((Binding.name (mode_cbasename ^ "_def"), def), [])]
  1659         PureThy.add_defs false [((Binding.name (mode_cbasename ^ "_def"), def), [])]
  1616       val (intro, elim) =
  1660       val (intro, elim) =
  1617         create_intro_elim_rule mode definition mode_cname funT (Const (name, T)) thy'
  1661         create_intro_elim_rule mode definition mode_cname funT (Const (name, T)) thy'
  1618 			val _ = Output.tracing (Display.string_of_thm_global thy' definition)
       
  1619       in thy'
  1662       in thy'
  1620 			  |> add_predfun name mode (mode_cname, definition, intro, elim)
  1663 			  |> add_predfun name mode (mode_cname, definition, intro, elim)
  1621         |> PureThy.store_thm (Binding.name (mode_cbasename ^ "I"), intro) |> snd
  1664         |> PureThy.store_thm (Binding.name (mode_cbasename ^ "I"), intro) |> snd
  1622         |> PureThy.store_thm (Binding.name (mode_cbasename ^ "E"), elim)  |> snd
  1665         |> PureThy.store_thm (Binding.name (mode_cbasename ^ "E"), elim)  |> snd
  1623         |> Theory.checkpoint
  1666         |> Theory.checkpoint
  2118         fun all_smodes_of_typs Ts = cprods_subset (
  2161         fun all_smodes_of_typs Ts = cprods_subset (
  2119           map_index (fn (i, U) =>
  2162           map_index (fn (i, U) =>
  2120             case HOLogic.strip_tupleT U of
  2163             case HOLogic.strip_tupleT U of
  2121               [] => [(i + 1, NONE)]
  2164               [] => [(i + 1, NONE)]
  2122             | [U] => [(i + 1, NONE)]
  2165             | [U] => [(i + 1, NONE)]
  2123 	    | Us =>  map (pair (i + 1) o SOME) ((subsets 1 (length Us)) \\ [[], 1 upto (length Us)]))
  2166             | Us =>  (i + 1, NONE) ::
       
  2167               (map (pair (i + 1) o SOME) ((subsets 1 (length Us)) \\ [[], 1 upto (length Us)])))
  2124           Ts)
  2168           Ts)
  2125       in
  2169       in
  2126         cprod (cprods (map (fn T => case strip_type T of
  2170         cprod (cprods (map (fn T => case strip_type T of
  2127           (Rs as _ :: _, Type ("bool", [])) => map SOME (all_smodes_of_typs Rs) | _ => [NONE]) Ts),
  2171           (Rs as _ :: _, Type ("bool", [])) => map SOME (all_smodes_of_typs Rs) | _ => [NONE]) Ts),
  2128            all_smodes_of_typs Us)
  2172            all_smodes_of_typs Us)
  2218   are_not_defined = (fn thy => fn preds => true), (* TODO *)
  2262   are_not_defined = (fn thy => fn preds => true), (* TODO *)
  2219   qname = "rpred_equation"}
  2263   qname = "rpred_equation"}
  2220 
  2264 
  2221 (** user interface **)
  2265 (** user interface **)
  2222 
  2266 
  2223 (* generation of case rules from user-given introduction rules *)
       
  2224 
       
  2225 fun mk_casesrule ctxt nparams introrules =
       
  2226   let
       
  2227     val intros = map (Logic.unvarify o prop_of) introrules
       
  2228     val (pred, (params, args)) = strip_intro_concl nparams (hd intros)
       
  2229     val ([propname], ctxt1) = Variable.variant_fixes ["thesis"] ctxt
       
  2230     val prop = HOLogic.mk_Trueprop (Free (propname, HOLogic.boolT))
       
  2231     val (argnames, ctxt2) = Variable.variant_fixes
       
  2232       (map (fn i => "a" ^ string_of_int i) (1 upto (length args))) ctxt1
       
  2233     val argvs = map2 (curry Free) argnames (map fastype_of args)
       
  2234     fun mk_case intro =
       
  2235       let
       
  2236         val (_, (_, args)) = strip_intro_concl nparams intro
       
  2237         val prems = Logic.strip_imp_prems intro
       
  2238         val eqprems = map (HOLogic.mk_Trueprop o HOLogic.mk_eq) (argvs ~~ args)
       
  2239         val frees = (fold o fold_aterms)
       
  2240           (fn t as Free _ =>
       
  2241               if member (op aconv) params t then I else insert (op aconv) t
       
  2242            | _ => I) (args @ prems) []
       
  2243       in fold Logic.all frees (Logic.list_implies (eqprems @ prems, prop)) end
       
  2244     val assm = HOLogic.mk_Trueprop (list_comb (pred, params @ argvs))
       
  2245     val cases = map mk_case intros
       
  2246   in Logic.list_implies (assm :: cases, prop) end;
       
  2247 
       
  2248 (* code_pred_intro attribute *)
  2267 (* code_pred_intro attribute *)
  2249 
  2268 
  2250 fun attrib f = Thm.declaration_attribute (fn thm => Context.mapping (f thm) I);
  2269 fun attrib f = Thm.declaration_attribute (fn thm => Context.mapping (f thm) I);
  2251 
  2270 
  2252 val code_pred_intros_attrib = attrib add_intro;
  2271 val code_pred_intros_attrib = attrib add_intro;
  2253 
  2272 
  2254 local
  2273 
       
  2274 (*FIXME
       
  2275 - Naming of auxiliary rules necessary?
       
  2276 - add default code equations P x y z = P_i_i_i x y z
       
  2277 *)
       
  2278 
       
  2279 val setup = PredData.put (Graph.empty) #>
       
  2280   Attrib.setup @{binding code_pred_intros} (Scan.succeed (attrib add_intro))
       
  2281     "adding alternative introduction rules for code generation of inductive predicates"
       
  2282 (*  Attrib.setup @{binding code_ind_cases} (Scan.succeed add_elim_attrib)
       
  2283     "adding alternative elimination rules for code generation of inductive predicates";
       
  2284     *)
       
  2285   (*FIXME name discrepancy in attribs and ML code*)
       
  2286   (*FIXME intros should be better named intro*)
       
  2287   (*FIXME why distinguished attribute for cases?*)
  2255 
  2288 
  2256 (* TODO: make TheoryDataFun to GenericDataFun & remove duplication of local theory and theory *)
  2289 (* TODO: make TheoryDataFun to GenericDataFun & remove duplication of local theory and theory *)
  2257 fun generic_code_pred prep_const raw_const lthy =
  2290 fun generic_code_pred prep_const rpred raw_const lthy =
  2258   let
  2291   let
  2259     val thy = ProofContext.theory_of lthy
  2292     val thy = ProofContext.theory_of lthy
  2260     val const = prep_const thy raw_const
  2293     val const = prep_const thy raw_const
  2261     val lthy' = LocalTheory.theory (PredData.map
  2294     val lthy' = LocalTheory.theory (PredData.map
  2262         (extend (fetch_pred_data thy) (depending_preds_of thy) const)) lthy
  2295         (extend (fetch_pred_data thy) (depending_preds_of thy) const)) lthy
  2280     fun after_qed thms goal_ctxt =
  2313     fun after_qed thms goal_ctxt =
  2281       let
  2314       let
  2282         val global_thms = ProofContext.export goal_ctxt
  2315         val global_thms = ProofContext.export goal_ctxt
  2283           (ProofContext.init (ProofContext.theory_of goal_ctxt)) (map the_single thms)
  2316           (ProofContext.init (ProofContext.theory_of goal_ctxt)) (map the_single thms)
  2284       in
  2317       in
  2285         goal_ctxt |> LocalTheory.theory (fold set_elim global_thms #> add_equations [const])
  2318         goal_ctxt |> LocalTheory.theory (fold set_elim global_thms #>
       
  2319           (if rpred then
       
  2320           (add_sizelim_equations [const] #> add_quickcheck_equations [const])
       
  2321         else add_equations [const]))
  2286       end  
  2322       end  
  2287   in
  2323   in
  2288     Proof.theorem_i NONE after_qed (map (single o (rpair [])) cases_rules) lthy''
  2324     Proof.theorem_i NONE after_qed (map (single o (rpair [])) cases_rules) lthy''
  2289   end;
  2325   end;
  2290 
       
  2291 structure P = OuterParse
       
  2292 
       
  2293 in
       
  2294 
  2326 
  2295 val code_pred = generic_code_pred (K I);
  2327 val code_pred = generic_code_pred (K I);
  2296 val code_pred_cmd = generic_code_pred Code.read_const
  2328 val code_pred_cmd = generic_code_pred Code.read_const
  2297 
       
  2298 val setup = PredData.put (Graph.empty) #>
       
  2299   Attrib.setup @{binding code_pred_intros} (Scan.succeed (attrib add_intro))
       
  2300     "adding alternative introduction rules for code generation of inductive predicates"
       
  2301 (*  Attrib.setup @{binding code_ind_cases} (Scan.succeed add_elim_attrib)
       
  2302     "adding alternative elimination rules for code generation of inductive predicates";
       
  2303     *)
       
  2304   (*FIXME name discrepancy in attribs and ML code*)
       
  2305   (*FIXME intros should be better named intro*)
       
  2306   (*FIXME why distinguished attribute for cases?*)
       
  2307 
       
  2308 val _ = OuterSyntax.local_theory_to_proof "code_pred"
       
  2309   "prove equations for predicate specified by intro/elim rules"
       
  2310   OuterKeyword.thy_goal (P.term_group >> code_pred_cmd)
       
  2311 
       
  2312 end
       
  2313 
       
  2314 (*FIXME
       
  2315 - Naming of auxiliary rules necessary?
       
  2316 - add default code equations P x y z = P_i_i_i x y z
       
  2317 *)
       
  2318 
  2329 
  2319 (* transformation for code generation *)
  2330 (* transformation for code generation *)
  2320 
  2331 
  2321 val eval_ref = ref (NONE : (unit -> term Predicate.pred) option);
  2332 val eval_ref = ref (NONE : (unit -> term Predicate.pred) option);
  2322 
  2333 
  2340       | [m] => m
  2351       | [m] => m
  2341       | m :: _ :: _ => (warning ("Multiple modes possible for comprehension "
  2352       | m :: _ :: _ => (warning ("Multiple modes possible for comprehension "
  2342                 ^ Syntax.string_of_term_global thy t_compr); m);
  2353                 ^ Syntax.string_of_term_global thy t_compr); m);
  2343     val (inargs, outargs) = split_smode user_mode' args;
  2354     val (inargs, outargs) = split_smode user_mode' args;
  2344     val t_pred = list_comb (compile_expr NONE thy (m, list_comb (pred, params)), inargs);
  2355     val t_pred = list_comb (compile_expr NONE thy (m, list_comb (pred, params)), inargs);
  2345     val t_eval = if null outargs then t_pred else let
  2356     val t_eval = if null outargs then t_pred else
       
  2357       let
  2346         val outargs_bounds = map (fn Bound i => i) outargs;
  2358         val outargs_bounds = map (fn Bound i => i) outargs;
  2347         val outargsTs = map (nth Ts) outargs_bounds;
  2359         val outargsTs = map (nth Ts) outargs_bounds;
  2348         val T_pred = HOLogic.mk_tupleT outargsTs;
  2360         val T_pred = HOLogic.mk_tupleT outargsTs;
  2349         val T_compr = HOLogic.mk_ptupleT fp Ts;
  2361         val T_compr = HOLogic.mk_ptupleT fp Ts;
  2350         val arrange_bounds = map_index I outargs_bounds
  2362         val arrange_bounds = map_index I outargs_bounds
  2359 fun eval thy t_compr =
  2371 fun eval thy t_compr =
  2360   let
  2372   let
  2361     val t = analyze_compr thy t_compr;
  2373     val t = analyze_compr thy t_compr;
  2362     val T = dest_predT PredicateCompFuns.compfuns (fastype_of t);
  2374     val T = dest_predT PredicateCompFuns.compfuns (fastype_of t);
  2363     val t' = mk_map PredicateCompFuns.compfuns T HOLogic.termT (HOLogic.term_of_const T) t;
  2375     val t' = mk_map PredicateCompFuns.compfuns T HOLogic.termT (HOLogic.term_of_const T) t;
  2364   in (T, Code_ML.eval NONE ("Predicate_Compile.eval_ref", eval_ref) Predicate.map thy t' []) end;
  2376   in (T, Code_ML.eval NONE ("Predicate_Compile_Core.eval_ref", eval_ref) Predicate.map thy t' []) end;
  2365 
  2377 
  2366 fun values ctxt k t_compr =
  2378 fun values ctxt k t_compr =
  2367   let
  2379   let
  2368     val thy = ProofContext.theory_of ctxt;
  2380     val thy = ProofContext.theory_of ctxt;
  2369     val (T, t) = eval thy t_compr;
  2381     val (T, t) = eval thy t_compr;