src/HOL/Tools/Predicate_Compile/predicate_compile_aux.ML
changeset 40101 f7fc517e21c6
parent 40054 cd7b1fa20bce
child 40139 6a53d57fa902
equal deleted inserted replaced
40100:98d74bbe8cd8 40101:f7fc517e21c6
    51   val is_predT : typ -> bool
    51   val is_predT : typ -> bool
    52   val is_constrt : theory -> term -> bool
    52   val is_constrt : theory -> term -> bool
    53   val is_constr : Proof.context -> string -> bool
    53   val is_constr : Proof.context -> string -> bool
    54   val focus_ex : term -> Name.context -> ((string * typ) list * term) * Name.context
    54   val focus_ex : term -> Name.context -> ((string * typ) list * term) * Name.context
    55   val strip_all : term -> (string * typ) list * term
    55   val strip_all : term -> (string * typ) list * term
       
    56   val strip_intro_concl : thm -> term * term list
    56   (* introduction rule combinators *)
    57   (* introduction rule combinators *)
    57   val map_atoms : (term -> term) -> term -> term
    58   val map_atoms : (term -> term) -> term -> term
    58   val fold_atoms : (term -> 'a -> 'a) -> term -> 'a -> 'a
    59   val fold_atoms : (term -> 'a -> 'a) -> term -> 'a -> 'a
    59   val fold_map_atoms : (term -> 'a -> term * 'a) -> term -> 'a -> term * 'a
    60   val fold_map_atoms : (term -> 'a -> term * 'a) -> term -> 'a -> term * 'a
    60   val maps_premises : (term -> term list) -> term -> term
    61   val maps_premises : (term -> term list) -> term -> term
   155   val case_betapply : theory -> term -> term
   156   val case_betapply : theory -> term -> term
   156   val eta_contract_ho_arguments : theory -> thm -> thm
   157   val eta_contract_ho_arguments : theory -> thm -> thm
   157   val remove_equalities : theory -> thm -> thm
   158   val remove_equalities : theory -> thm -> thm
   158   val remove_pointless_clauses : thm -> thm list
   159   val remove_pointless_clauses : thm -> thm list
   159   val peephole_optimisation : theory -> thm -> thm option
   160   val peephole_optimisation : theory -> thm -> thm option
       
   161   (* auxillary *)
       
   162   val unify_consts : theory -> term list -> term list -> (term list * term list)
       
   163   val mk_casesrule : Proof.context -> term -> thm list -> term
       
   164   val preprocess_intro : theory -> thm -> thm
       
   165   
   160   val define_quickcheck_predicate :
   166   val define_quickcheck_predicate :
   161     term -> theory -> (((string * typ) * (string * typ) list) * thm) * theory
   167     term -> theory -> (((string * typ) * (string * typ) list) * thm) * theory
   162 end;
   168 end;
   163 
   169 
   164 structure Predicate_Compile_Aux : PREDICATE_COMPILE_AUX =
   170 structure Predicate_Compile_Aux : PREDICATE_COMPILE_AUX =
   544     val ps' = xs' ~~ Ts;
   550     val ps' = xs' ~~ Ts;
   545     val vs = map Free ps';
   551     val vs = map Free ps';
   546     val t'' = Term.subst_bounds (rev vs, t');
   552     val t'' = Term.subst_bounds (rev vs, t');
   547   in ((ps', t''), nctxt') end;
   553   in ((ps', t''), nctxt') end;
   548 
   554 
       
   555 val strip_intro_concl = (strip_comb o HOLogic.dest_Trueprop o Logic.strip_imp_concl o prop_of)
       
   556   
   549 (* introduction rule combinators *)
   557 (* introduction rule combinators *)
   550 
   558 
   551 fun map_atoms f intro = 
   559 fun map_atoms f intro = 
   552   let
   560   let
   553     val (literals, head) = Logic.strip_horn intro
   561     val (literals, head) = Logic.strip_horn intro
  1046   in
  1054   in
  1047     Option.map (Skip_Proof.make_thm thy)
  1055     Option.map (Skip_Proof.make_thm thy)
  1048       (process_False (process_True (prop_of (process intro))))
  1056       (process_False (process_True (prop_of (process intro))))
  1049   end
  1057   end
  1050 
  1058 
       
  1059 
       
  1060 (* importing introduction rules *)
       
  1061 
       
  1062 fun import_intros inp_pred [] ctxt =
       
  1063   let
       
  1064     val ([outp_pred], ctxt') = Variable.import_terms true [inp_pred] ctxt
       
  1065     val T = fastype_of outp_pred
       
  1066     val paramTs = ho_argsT_of_typ (binder_types T)
       
  1067     val (param_names, ctxt'') = Variable.variant_fixes
       
  1068       (map (fn i => "p" ^ (string_of_int i)) (1 upto (length paramTs))) ctxt'
       
  1069     val params = map2 (curry Free) param_names paramTs
       
  1070   in
       
  1071     (((outp_pred, params), []), ctxt')
       
  1072   end
       
  1073   | import_intros inp_pred (th :: ths) ctxt =
       
  1074     let
       
  1075       val ((_, [th']), ctxt') = Variable.import true [th] ctxt
       
  1076       val thy = ProofContext.theory_of ctxt'
       
  1077       val (pred, args) = strip_intro_concl th'
       
  1078       val T = fastype_of pred
       
  1079       val ho_args = ho_args_of_typ T args
       
  1080       fun subst_of (pred', pred) =
       
  1081         let
       
  1082           val subst = Sign.typ_match thy (fastype_of pred', fastype_of pred) Vartab.empty
       
  1083             handle Type.TYPE_MATCH => error ("Type mismatch of predicate " ^ fst (dest_Const pred)
       
  1084             ^ " (trying to match " ^ Syntax.string_of_typ ctxt (fastype_of pred')
       
  1085             ^ " and " ^ Syntax.string_of_typ ctxt (fastype_of pred) ^ ")"
       
  1086             ^ " in " ^ Display.string_of_thm ctxt th)
       
  1087         in map (fn (indexname, (s, T)) => ((indexname, s), T)) (Vartab.dest subst) end
       
  1088       fun instantiate_typ th =
       
  1089         let
       
  1090           val (pred', _) = strip_intro_concl th
       
  1091           val _ = if not (fst (dest_Const pred) = fst (dest_Const pred')) then
       
  1092             raise Fail "Trying to instantiate another predicate" else ()
       
  1093         in Thm.certify_instantiate (subst_of (pred', pred), []) th end;
       
  1094       fun instantiate_ho_args th =
       
  1095         let
       
  1096           val (_, args') = (strip_comb o HOLogic.dest_Trueprop o Logic.strip_imp_concl o prop_of) th
       
  1097           val ho_args' = map dest_Var (ho_args_of_typ T args')
       
  1098         in Thm.certify_instantiate ([], ho_args' ~~ ho_args) th end
       
  1099       val outp_pred =
       
  1100         Term_Subst.instantiate (subst_of (inp_pred, pred), []) inp_pred
       
  1101       val ((_, ths'), ctxt1) =
       
  1102         Variable.import false (map (instantiate_typ #> instantiate_ho_args) ths) ctxt'
       
  1103     in
       
  1104       (((outp_pred, ho_args), th' :: ths'), ctxt1)
       
  1105     end
       
  1106   
       
  1107 (* generation of case rules from user-given introduction rules *)
       
  1108 
       
  1109 fun mk_args2 (Type (@{type_name Product_Type.prod}, [T1, T2])) st =
       
  1110     let
       
  1111       val (t1, st') = mk_args2 T1 st
       
  1112       val (t2, st'') = mk_args2 T2 st'
       
  1113     in
       
  1114       (HOLogic.mk_prod (t1, t2), st'')
       
  1115     end
       
  1116   (*| mk_args2 (T as Type ("fun", _)) (params, ctxt) = 
       
  1117     let
       
  1118       val (S, U) = strip_type T
       
  1119     in
       
  1120       if U = HOLogic.boolT then
       
  1121         (hd params, (tl params, ctxt))
       
  1122       else
       
  1123         let
       
  1124           val ([x], ctxt') = Variable.variant_fixes ["x"] ctxt
       
  1125         in
       
  1126           (Free (x, T), (params, ctxt'))
       
  1127         end
       
  1128     end*)
       
  1129   | mk_args2 T (params, ctxt) =
       
  1130     let
       
  1131       val ([x], ctxt') = Variable.variant_fixes ["x"] ctxt
       
  1132     in
       
  1133       (Free (x, T), (params, ctxt'))
       
  1134     end
       
  1135 
       
  1136 fun mk_casesrule ctxt pred introrules =
       
  1137   let
       
  1138     (* TODO: can be simplified if parameters are not treated specially ? *)
       
  1139     val (((pred, params), intros_th), ctxt1) = import_intros pred introrules ctxt
       
  1140     (* TODO: distinct required ? -- test case with more than one parameter! *)
       
  1141     val params = distinct (op aconv) params
       
  1142     val intros = map prop_of intros_th
       
  1143     val ([propname], ctxt2) = Variable.variant_fixes ["thesis"] ctxt1
       
  1144     val prop = HOLogic.mk_Trueprop (Free (propname, HOLogic.boolT))
       
  1145     val argsT = binder_types (fastype_of pred)
       
  1146     (* TODO: can be simplified if parameters are not treated specially ? <-- see uncommented code! *)
       
  1147     val (argvs, _) = fold_map mk_args2 argsT (params, ctxt2)
       
  1148     fun mk_case intro =
       
  1149       let
       
  1150         val (_, args) = (strip_comb o HOLogic.dest_Trueprop o Logic.strip_imp_concl) intro
       
  1151         val prems = Logic.strip_imp_prems intro
       
  1152         val eqprems =
       
  1153           map2 (HOLogic.mk_Trueprop oo (curry HOLogic.mk_eq)) argvs args
       
  1154         val frees = map Free (fold Term.add_frees (args @ prems) [])
       
  1155       in fold Logic.all frees (Logic.list_implies (eqprems @ prems, prop)) end
       
  1156     val assm = HOLogic.mk_Trueprop (list_comb (pred, argvs))
       
  1157     val cases = map mk_case intros
       
  1158   in Logic.list_implies (assm :: cases, prop) end;
       
  1159   
       
  1160 
       
  1161 (* unifying constants to have the same type variables *)
       
  1162 
       
  1163 fun unify_consts thy cs intr_ts =
       
  1164   (let
       
  1165      val add_term_consts_2 = fold_aterms (fn Const c => insert (op =) c | _ => I);
       
  1166      fun varify (t, (i, ts)) =
       
  1167        let val t' = map_types (Logic.incr_tvar (i + 1)) (#2 (Type.varify_global [] t))
       
  1168        in (maxidx_of_term t', t'::ts) end;
       
  1169      val (i, cs') = List.foldr varify (~1, []) cs;
       
  1170      val (i', intr_ts') = List.foldr varify (i, []) intr_ts;
       
  1171      val rec_consts = fold add_term_consts_2 cs' [];
       
  1172      val intr_consts = fold add_term_consts_2 intr_ts' [];
       
  1173      fun unify (cname, cT) =
       
  1174        let val consts = map snd (filter (fn c => fst c = cname) intr_consts)
       
  1175        in fold (Sign.typ_unify thy) ((replicate (length consts) cT) ~~ consts) end;
       
  1176      val (env, _) = fold unify rec_consts (Vartab.empty, i');
       
  1177      val subst = map_types (Envir.norm_type env)
       
  1178    in (map subst cs', map subst intr_ts')
       
  1179    end) handle Type.TUNIFY =>
       
  1180      (warning "Occurrences of recursive constant have non-unifiable types"; (cs, intr_ts));
       
  1181 
       
  1182 (* preprocessing rules *)
       
  1183 
       
  1184 fun Trueprop_conv cv ct =
       
  1185   case Thm.term_of ct of
       
  1186     Const (@{const_name Trueprop}, _) $ _ => Conv.arg_conv cv ct  
       
  1187   | _ => raise Fail "Trueprop_conv"
       
  1188 
       
  1189 fun preprocess_equality thy rule =
       
  1190   Conv.fconv_rule
       
  1191     (imp_prems_conv
       
  1192       (Trueprop_conv (Conv.try_conv (Conv.rewr_conv (Thm.symmetric @{thm Predicate.eq_is_eq})))))
       
  1193     (Thm.transfer thy rule)
       
  1194 
       
  1195 fun preprocess_intro thy = expand_tuples thy #> preprocess_equality thy
       
  1196 
  1051 (* defining a quickcheck predicate *)
  1197 (* defining a quickcheck predicate *)
  1052 
  1198 
  1053 fun strip_imp_prems (Const(@{const_name HOL.implies}, _) $ A $ B) = A :: strip_imp_prems B
  1199 fun strip_imp_prems (Const(@{const_name HOL.implies}, _) $ A $ B) = A :: strip_imp_prems B
  1054   | strip_imp_prems _ = [];
  1200   | strip_imp_prems _ = [];
  1055 
  1201