allowed less exhaustive patterns
authornoschinl
Fri, 06 Sep 2013 10:56:40 +0200
changeset 545669d9945941eab
parent 54565 3083c611ec40
child 54567 d92578436d47
allowed less exhaustive patterns
src/HOL/Library/simps_case_conv.ML
     1.1 --- a/src/HOL/Library/simps_case_conv.ML	Fri Sep 06 10:56:40 2013 +0200
     1.2 +++ b/src/HOL/Library/simps_case_conv.ML	Fri Sep 06 10:56:40 2013 +0200
     1.3 @@ -32,12 +32,59 @@
     1.4  
     1.5  local
     1.6  
     1.7 -(*Creates free variables for a list of types*)
     1.8 -fun mk_Frees Ts ctxt =
     1.9 +  fun transpose [] = []
    1.10 +    | transpose ([] :: xss) = transpose xss
    1.11 +    | transpose xss = map hd xss :: transpose (map tl xss);
    1.12 +
    1.13 +  fun same_fun (ts as _ $ _ :: _) =
    1.14 +      let
    1.15 +        val (fs, argss) = map strip_comb ts |> split_list
    1.16 +        val f = hd fs
    1.17 +      in if forall (fn x => f = x) fs then SOME (f, argss) else NONE end
    1.18 +    | same_fun _ = NONE
    1.19 +
    1.20 +  (* pats must be non-empty *)
    1.21 +  fun split_pat pats ctxt =
    1.22 +      case same_fun pats of
    1.23 +        NONE =>
    1.24 +          let
    1.25 +            val (name, ctxt') = yield_singleton Variable.variant_fixes "x" ctxt
    1.26 +            val var = Free (name, fastype_of (hd pats))
    1.27 +          in (((var, [var]), map single pats), ctxt') end
    1.28 +      | SOME (f, argss) =>
    1.29 +          let
    1.30 +            val (((def_pats, def_frees), case_patss), ctxt') =
    1.31 +              split_pats argss ctxt
    1.32 +            val def_pat = list_comb (f, def_pats)
    1.33 +          in (((def_pat, flat def_frees), case_patss), ctxt') end
    1.34 +  and
    1.35 +      split_pats patss ctxt =
    1.36 +        let
    1.37 +          val (splitted, ctxt') = fold_map split_pat (transpose patss) ctxt
    1.38 +          val r = splitted |> split_list |> apfst split_list |> apsnd (transpose #> map flat)
    1.39 +        in (r, ctxt') end
    1.40 +
    1.41 +(*
    1.42 +  Takes a list lhss of left hand sides (which are lists of patterns)
    1.43 +  and a list rhss of right hand sides. Returns
    1.44 +    - a single equation with a (nested) case-expression on the rhs
    1.45 +    - a list of all split-thms needed to split the rhs
    1.46 +  Patterns which have the same outer context in all lhss remain
    1.47 +  on the lhs of the computed equation.
    1.48 +*)
    1.49 +fun build_case_t fun_t lhss rhss ctxt =
    1.50    let
    1.51 -    val (names,ctxt') = Variable.variant_fixes (replicate (length Ts) "x") ctxt
    1.52 -    val ts = map Free (names ~~ Ts)
    1.53 -  in (ts, ctxt') end
    1.54 +    val (((def_pats, def_frees), case_patss), ctxt') =
    1.55 +      split_pats lhss ctxt
    1.56 +    val pattern = map HOLogic.mk_tuple case_patss
    1.57 +    val case_arg = HOLogic.mk_tuple (flat def_frees)
    1.58 +    val cases = Case_Translation.make_case ctxt' Case_Translation.Warning Name.context
    1.59 +      case_arg (pattern ~~ rhss)
    1.60 +    val split_thms = get_split_ths (Proof_Context.theory_of ctxt') (fastype_of case_arg)
    1.61 +    val t = (list_comb (fun_t, def_pats), cases)
    1.62 +      |> HOLogic.mk_eq
    1.63 +      |> HOLogic.mk_Trueprop
    1.64 +  in ((t, split_thms), ctxt') end
    1.65  
    1.66  fun tac ctxt {splits, intros, defs} =
    1.67    let val ctxt' = Classical.addSIs (ctxt, intros) in
    1.68 @@ -67,16 +114,16 @@
    1.69      f p_mn ... p_mn = tm
    1.70    of theorems, prove a single theorem
    1.71      f x1 ... xn = t
    1.72 -  where t is a (nested) case expression. The terms p_11, ..., p_mn must
    1.73 -  be exhaustive, non-overlapping datatype patterns. f must not be a function
    1.74 -  application.
    1.75 +  where t is a (nested) case expression. f must not be a function
    1.76 +  application. Moreover, the terms p_11, ..., p_mn must be non-overlapping
    1.77 +  datatype patterns. The patterns must be exhausting up to common constructor
    1.78 +  contexts.
    1.79  *)
    1.80  fun to_case ctxt ths =
    1.81    let
    1.82      val (iths, ctxt') = import ths ctxt
    1.83 -    val (fun_t, arg_ts) = hd iths |> strip_eq |> fst |> strip_comb
    1.84 +    val fun_t = hd iths |> strip_eq |> fst |> head_of
    1.85      val eqs = map (strip_eq #> apfst (snd o strip_comb)) iths
    1.86 -    val (arg_Frees, ctxt'') = mk_Frees (map fastype_of arg_ts) ctxt'
    1.87  
    1.88      fun hide_rhs ((pat, rhs), name) lthy = let
    1.89          val frees = fold Term.add_frees pat []
    1.90 @@ -85,23 +132,13 @@
    1.91            ((Binding.name name, Mixfix.NoSyn), abs_rhs) lthy
    1.92        in ((list_comb (f, map Free (rev frees)), def), lthy') end
    1.93  
    1.94 -    val ((def_ts, def_thms), ctxt3) = let
    1.95 -        val nctxt = Variable.names_of ctxt''
    1.96 +    val ((def_ts, def_thms), ctxt2) = let
    1.97 +        val nctxt = Variable.names_of ctxt'
    1.98          val names = Name.invent nctxt "rhs" (length eqs)
    1.99 -      in fold_map hide_rhs (eqs ~~ names) ctxt'' |> apfst split_list end
   1.100 +      in fold_map hide_rhs (eqs ~~ names) ctxt' |> apfst split_list end
   1.101  
   1.102 -    val (cases, split_thms) =
   1.103 -      let
   1.104 -        val pattern = map (fst #> HOLogic.mk_tuple) eqs
   1.105 -        val case_arg = HOLogic.mk_tuple arg_Frees
   1.106 -        val cases = Case_Translation.make_case ctxt Case_Translation.Warning Name.context
   1.107 -          case_arg (pattern ~~ def_ts)
   1.108 -        val split_thms = get_split_ths (Proof_Context.theory_of ctxt3) (fastype_of case_arg)
   1.109 -      in (cases, split_thms) end
   1.110 +    val ((t, split_thms), ctxt3) = build_case_t fun_t (map fst eqs) def_ts ctxt2
   1.111  
   1.112 -    val t = (list_comb (fun_t, arg_Frees), cases)
   1.113 -      |> HOLogic.mk_eq
   1.114 -      |> HOLogic.mk_Trueprop
   1.115      val th = Goal.prove ctxt3 [] [] t (fn {context=ctxt, ...} =>
   1.116            tac ctxt {splits=split_thms, intros=ths, defs=def_thms})
   1.117    in th