src/HOL/Tools/Datatype/datatype_case.ML
author wenzelm
Sun, 14 Feb 2010 00:26:48 +0100
changeset 35124 33976519c888
parent 33969 1e7ca47c6c3d
child 35140 c8a6fae0ad0c
permissions -rw-r--r--
formal markup of constants;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
33968
f94fb13ecbb3 modernized structures and tuned headers of datatype package modules; joined former datatype.ML and datatype_rep_proofs.ML
haftmann
parents: 33040
diff changeset
     1
(*  Title:      HOL/Tools/Datatype/datatype_case.ML
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
     2
    Author:     Konrad Slind, Cambridge University Computer Laboratory
29266
4a478f9d2847 use regular Term.add_vars, Term.add_frees etc.;
wenzelm
parents: 26931
diff changeset
     3
    Author:     Stefan Berghofer, TU Muenchen
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
     4
33968
f94fb13ecbb3 modernized structures and tuned headers of datatype package modules; joined former datatype.ML and datatype_rep_proofs.ML
haftmann
parents: 33040
diff changeset
     5
Datatype package: nested case expressions on datatypes.
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
     6
*)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
     7
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
     8
signature DATATYPE_CASE =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
     9
sig
33968
f94fb13ecbb3 modernized structures and tuned headers of datatype package modules; joined former datatype.ML and datatype_rep_proofs.ML
haftmann
parents: 33040
diff changeset
    10
  datatype config = Error | Warning | Quiet
f94fb13ecbb3 modernized structures and tuned headers of datatype package modules; joined former datatype.ML and datatype_rep_proofs.ML
haftmann
parents: 33040
diff changeset
    11
  type info = Datatype_Aux.info
f94fb13ecbb3 modernized structures and tuned headers of datatype package modules; joined former datatype.ML and datatype_rep_proofs.ML
haftmann
parents: 33040
diff changeset
    12
  val make_case: (string * typ -> info option) ->
32671
fbd224850767 adapted configuration for DatatypeCase.make_case
bulwahn
parents: 32035
diff changeset
    13
    Proof.context -> config -> string list -> term -> (term * term) list ->
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    14
    term * (term * (int * bool)) list
33968
f94fb13ecbb3 modernized structures and tuned headers of datatype package modules; joined former datatype.ML and datatype_rep_proofs.ML
haftmann
parents: 33040
diff changeset
    15
  val dest_case: (string -> info option) -> bool ->
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    16
    string list -> term -> (term * (term * term) list) option
33968
f94fb13ecbb3 modernized structures and tuned headers of datatype package modules; joined former datatype.ML and datatype_rep_proofs.ML
haftmann
parents: 33040
diff changeset
    17
  val strip_case: (string -> info option) -> bool ->
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    18
    term -> (term * (term * term) list) option
33968
f94fb13ecbb3 modernized structures and tuned headers of datatype package modules; joined former datatype.ML and datatype_rep_proofs.ML
haftmann
parents: 33040
diff changeset
    19
  val case_tr: bool -> (theory -> string * typ -> info option) ->
f94fb13ecbb3 modernized structures and tuned headers of datatype package modules; joined former datatype.ML and datatype_rep_proofs.ML
haftmann
parents: 33040
diff changeset
    20
    Proof.context -> term list -> term
f94fb13ecbb3 modernized structures and tuned headers of datatype package modules; joined former datatype.ML and datatype_rep_proofs.ML
haftmann
parents: 33040
diff changeset
    21
  val case_tr': (theory -> string -> info option) ->
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    22
    string -> Proof.context -> term list -> term
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    23
end;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    24
33968
f94fb13ecbb3 modernized structures and tuned headers of datatype package modules; joined former datatype.ML and datatype_rep_proofs.ML
haftmann
parents: 33040
diff changeset
    25
structure Datatype_Case : DATATYPE_CASE =
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    26
struct
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    27
32671
fbd224850767 adapted configuration for DatatypeCase.make_case
bulwahn
parents: 32035
diff changeset
    28
datatype config = Error | Warning | Quiet;
33968
f94fb13ecbb3 modernized structures and tuned headers of datatype package modules; joined former datatype.ML and datatype_rep_proofs.ML
haftmann
parents: 33040
diff changeset
    29
type info = Datatype_Aux.info;
32671
fbd224850767 adapted configuration for DatatypeCase.make_case
bulwahn
parents: 32035
diff changeset
    30
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    31
exception CASE_ERROR of string * int;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    32
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    33
fun match_type thy pat ob = Sign.typ_match thy (pat, ob) Vartab.empty;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    34
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    35
(*---------------------------------------------------------------------------
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    36
 * Get information about datatypes
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    37
 *---------------------------------------------------------------------------*)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    38
32896
99cd75a18b78 lookup for datatype constructors considers type annotations to resolve overloading
haftmann
parents: 32671
diff changeset
    39
fun ty_info tab sT =
99cd75a18b78 lookup for datatype constructors considers type annotations to resolve overloading
haftmann
parents: 32671
diff changeset
    40
  case tab sT of
33968
f94fb13ecbb3 modernized structures and tuned headers of datatype package modules; joined former datatype.ML and datatype_rep_proofs.ML
haftmann
parents: 33040
diff changeset
    41
    SOME ({descr, case_name, index, sorts, ...} : info) =>
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    42
      let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    43
        val (_, (tname, dts, constrs)) = nth descr index;
33968
f94fb13ecbb3 modernized structures and tuned headers of datatype package modules; joined former datatype.ML and datatype_rep_proofs.ML
haftmann
parents: 33040
diff changeset
    44
        val mk_ty = Datatype_Aux.typ_of_dtyp descr sorts;
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
    45
        val T = Type (tname, map mk_ty dts);
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    46
      in
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    47
        SOME {case_name = case_name,
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    48
          constructors = map (fn (cname, dts') =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    49
            Const (cname, Logic.varifyT (map mk_ty dts' ---> T))) constrs}
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    50
      end
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    51
  | NONE => NONE;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    52
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    53
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    54
(*---------------------------------------------------------------------------
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    55
 * Each pattern carries with it a tag (i,b) where
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    56
 * i is the clause it came from and
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    57
 * b=true indicates that clause was given by the user
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    58
 * (or is an instantiation of a user supplied pattern)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    59
 * b=false --> i = ~1
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    60
 *---------------------------------------------------------------------------*)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    61
29281
b22ccb3998db eliminated OldTerm.add_term_free_names;
wenzelm
parents: 29270
diff changeset
    62
fun pattern_subst theta (tm, x) = (subst_free theta tm, x);
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    63
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    64
fun row_of_pat x = fst (snd x);
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    65
29281
b22ccb3998db eliminated OldTerm.add_term_free_names;
wenzelm
parents: 29270
diff changeset
    66
fun add_row_used ((prfx, pats), (tm, tag)) =
b22ccb3998db eliminated OldTerm.add_term_free_names;
wenzelm
parents: 29270
diff changeset
    67
  fold Term.add_free_names (tm :: pats @ prfx);
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    68
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    69
(* try to preserve names given by user *)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    70
fun default_names names ts =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    71
  map (fn ("", Free (name', _)) => name' | (name, _) => name) (names ~~ ts);
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    72
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
    73
fun strip_constraints (Const (@{syntax_const "_constrain"}, _) $ t $ tT) =
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    74
      strip_constraints t ||> cons tT
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    75
  | strip_constraints t = (t, []);
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    76
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
    77
fun mk_fun_constrain tT t =
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
    78
  Syntax.const @{syntax_const "_constrain"} $ t $
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
    79
    (Syntax.free "fun" $ tT $ Syntax.free "dummy");    (* FIXME @{type_syntax} (!?) *)
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    80
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    81
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    82
(*---------------------------------------------------------------------------
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    83
 * Produce an instance of a constructor, plus genvars for its arguments.
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    84
 *---------------------------------------------------------------------------*)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    85
fun fresh_constr ty_match ty_inst colty used c =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    86
  let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    87
    val (_, Ty) = dest_Const c
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    88
    val Ts = binder_types Ty;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    89
    val names = Name.variant_list used
33968
f94fb13ecbb3 modernized structures and tuned headers of datatype package modules; joined former datatype.ML and datatype_rep_proofs.ML
haftmann
parents: 33040
diff changeset
    90
      (Datatype_Prop.make_tnames (map Logic.unvarifyT Ts));
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    91
    val ty = body_type Ty;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    92
    val ty_theta = ty_match ty colty handle Type.TYPE_MATCH =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    93
      raise CASE_ERROR ("type mismatch", ~1)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    94
    val c' = ty_inst ty_theta c
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    95
    val gvars = map (ty_inst ty_theta o Free) (names ~~ Ts)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    96
  in (c', gvars)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    97
  end;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    98
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
    99
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   100
(*---------------------------------------------------------------------------
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   101
 * Goes through a list of rows and picks out the ones beginning with a
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   102
 * pattern with constructor = name.
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   103
 *---------------------------------------------------------------------------*)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   104
fun mk_group (name, T) rows =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   105
  let val k = length (binder_types T)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   106
  in fold (fn (row as ((prfx, p :: rst), rhs as (_, (i, _)))) =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   107
    fn ((in_group, not_in_group), (names, cnstrts)) => (case strip_comb p of
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   108
        (Const (name', _), args) =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   109
          if name = name' then
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   110
            if length args = k then
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   111
              let val (args', cnstrts') = split_list (map strip_constraints args)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   112
              in
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   113
                ((((prfx, args' @ rst), rhs) :: in_group, not_in_group),
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   114
                 (default_names names args', map2 append cnstrts cnstrts'))
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   115
              end
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   116
            else raise CASE_ERROR
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   117
              ("Wrong number of arguments for constructor " ^ name, i)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   118
          else ((in_group, row :: not_in_group), (names, cnstrts))
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   119
      | _ => raise CASE_ERROR ("Not a constructor pattern", i)))
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   120
    rows (([], []), (replicate k "", replicate k [])) |>> pairself rev
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   121
  end;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   122
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   123
(*---------------------------------------------------------------------------
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   124
 * Partition the rows. Not efficient: we should use hashing.
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   125
 *---------------------------------------------------------------------------*)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   126
fun partition _ _ _ _ _ _ _ [] = raise CASE_ERROR ("partition: no rows", ~1)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   127
  | partition ty_match ty_inst type_of used constructors colty res_ty
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   128
        (rows as (((prfx, _ :: rstp), _) :: _)) =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   129
      let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   130
        fun part {constrs = [], rows = [], A} = rev A
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   131
          | part {constrs = [], rows = (_, (_, (i, _))) :: _, A} =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   132
              raise CASE_ERROR ("Not a constructor pattern", i)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   133
          | part {constrs = c :: crst, rows, A} =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   134
              let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   135
                val ((in_group, not_in_group), (names, cnstrts)) =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   136
                  mk_group (dest_Const c) rows;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   137
                val used' = fold add_row_used in_group used;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   138
                val (c', gvars) = fresh_constr ty_match ty_inst colty used' c;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   139
                val in_group' =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   140
                  if null in_group  (* Constructor not given *)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   141
                  then
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   142
                    let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   143
                      val Ts = map type_of rstp;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   144
                      val xs = Name.variant_list
29281
b22ccb3998db eliminated OldTerm.add_term_free_names;
wenzelm
parents: 29270
diff changeset
   145
                        (fold Term.add_free_names gvars used')
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   146
                        (replicate (length rstp) "x")
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   147
                    in
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   148
                      [((prfx, gvars @ map Free (xs ~~ Ts)),
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   149
                        (Const (@{const_name HOL.undefined}, res_ty), (~1, false)))]
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   150
                    end
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   151
                  else in_group
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   152
              in
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   153
                part{constrs = crst,
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   154
                  rows = not_in_group,
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   155
                  A = {constructor = c',
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   156
                    new_formals = gvars,
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   157
                    names = names,
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   158
                    constraints = cnstrts,
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   159
                    group = in_group'} :: A}
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   160
              end
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   161
      in part {constrs = constructors, rows = rows, A = []}
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   162
      end;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   163
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   164
(*---------------------------------------------------------------------------
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   165
 * Misc. routines used in mk_case
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   166
 *---------------------------------------------------------------------------*)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   167
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   168
fun mk_pat ((c, c'), l) =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   169
  let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   170
    val L = length (binder_types (fastype_of c))
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   171
    fun build (prfx, tag, plist) =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   172
      let val (args, plist') = chop L plist
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   173
      in (prfx, tag, list_comb (c', args) :: plist') end
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   174
  in map build l end;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   175
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   176
fun v_to_prfx (prfx, v::pats) = (v::prfx,pats)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   177
  | v_to_prfx _ = raise CASE_ERROR ("mk_case: v_to_prfx", ~1);
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   178
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   179
fun v_to_pats (v::prfx,tag, pats) = (prfx, tag, v::pats)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   180
  | v_to_pats _ = raise CASE_ERROR ("mk_case: v_to_pats", ~1);
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   181
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   182
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   183
(*----------------------------------------------------------------------------
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   184
 * Translation of pattern terms into nested case expressions.
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   185
 *
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   186
 * This performs the translation and also builds the full set of patterns.
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   187
 * Thus it supports the construction of induction theorems even when an
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   188
 * incomplete set of patterns is given.
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   189
 *---------------------------------------------------------------------------*)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   190
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   191
fun mk_case tab ctxt ty_match ty_inst type_of used range_ty =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   192
  let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   193
    val name = Name.variant used "a";
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   194
    fun expand constructors used ty ((_, []), _) =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   195
          raise CASE_ERROR ("mk_case: expand_var_row", ~1)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   196
      | expand constructors used ty (row as ((prfx, p :: rst), rhs)) =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   197
          if is_Free p then
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   198
            let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   199
              val used' = add_row_used row used;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   200
              fun expnd c =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   201
                let val capp =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   202
                  list_comb (fresh_constr ty_match ty_inst ty used' c)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   203
                in ((prfx, capp :: rst), pattern_subst [(p, capp)] rhs)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   204
                end
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   205
            in map expnd constructors end
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   206
          else [row]
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   207
    fun mk {rows = [], ...} = raise CASE_ERROR ("no rows", ~1)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   208
      | mk {path = [], rows = ((prfx, []), (tm, tag)) :: _} =  (* Done *)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   209
          ([(prfx, tag, [])], tm)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   210
      | mk {path, rows as ((row as ((_, [Free _]), _)) :: _ :: _)} =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   211
          mk {path = path, rows = [row]}
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   212
      | mk {path = u :: rstp, rows as ((_, _ :: _), _) :: _} =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   213
          let val col0 = map (fn ((_, p :: _), (_, (i, _))) => (p, i)) rows
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   214
          in case Option.map (apfst head_of)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   215
            (find_first (not o is_Free o fst) col0) of
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   216
              NONE =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   217
                let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   218
                  val rows' = map (fn ((v, _), row) => row ||>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   219
                    pattern_subst [(v, u)] |>> v_to_prfx) (col0 ~~ rows);
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   220
                  val (pref_patl, tm) = mk {path = rstp, rows = rows'}
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   221
                in (map v_to_pats pref_patl, tm) end
32896
99cd75a18b78 lookup for datatype constructors considers type annotations to resolve overloading
haftmann
parents: 32671
diff changeset
   222
            | SOME (Const (cname, cT), i) => (case ty_info tab (cname, cT) of
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   223
                NONE => raise CASE_ERROR ("Not a datatype constructor: " ^ cname, i)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   224
              | SOME {case_name, constructors} =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   225
                let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   226
                  val pty = body_type cT;
29281
b22ccb3998db eliminated OldTerm.add_term_free_names;
wenzelm
parents: 29270
diff changeset
   227
                  val used' = fold Term.add_free_names rstp used;
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   228
                  val nrows = maps (expand constructors used' pty) rows;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   229
                  val subproblems = partition ty_match ty_inst type_of used'
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   230
                    constructors pty range_ty nrows;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   231
                  val constructors' = map #constructor subproblems
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   232
                  val news = map (fn {new_formals, group, ...} =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   233
                    {path = new_formals @ rstp, rows = group}) subproblems;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   234
                  val (pat_rect, dtrees) = split_list (map mk news);
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   235
                  val case_functions = map2
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   236
                    (fn {new_formals, names, constraints, ...} =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   237
                       fold_rev (fn ((x as Free (_, T), s), cnstrts) => fn t =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   238
                         Abs (if s = "" then name else s, T,
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   239
                           abstract_over (x, t)) |>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   240
                         fold mk_fun_constrain cnstrts)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   241
                           (new_formals ~~ names ~~ constraints))
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   242
                    subproblems dtrees;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   243
                  val types = map type_of (case_functions @ [u]);
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   244
                  val case_const = Const (case_name, types ---> range_ty)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   245
                  val tree = list_comb (case_const, case_functions @ [u])
32952
aeb1e44fbc19 replaced String.concat by implode;
wenzelm
parents: 32896
diff changeset
   246
                  val pat_rect1 = maps mk_pat (constructors ~~ constructors' ~~ pat_rect)
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   247
                in (pat_rect1, tree)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   248
                end)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   249
            | SOME (t, i) => raise CASE_ERROR ("Not a datatype constructor: " ^
24920
2a45e400fdad generic Syntax.pretty/string_of operations;
wenzelm
parents: 24349
diff changeset
   250
                Syntax.string_of_term ctxt t, i)
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   251
          end
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   252
      | mk _ = raise CASE_ERROR ("Malformed row matrix", ~1)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   253
  in mk
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   254
  end;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   255
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   256
fun case_error s = error ("Error in case expression:\n" ^ s);
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   257
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   258
(* Repeated variable occurrences in a pattern are not allowed. *)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   259
fun no_repeat_vars ctxt pat = fold_aterms
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   260
  (fn x as Free (s, _) => (fn xs =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   261
        if member op aconv xs x then
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   262
          case_error (quote s ^ " occurs repeatedly in the pattern " ^
24920
2a45e400fdad generic Syntax.pretty/string_of operations;
wenzelm
parents: 24349
diff changeset
   263
            quote (Syntax.string_of_term ctxt pat))
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   264
        else x :: xs)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   265
    | _ => I) pat [];
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   266
32671
fbd224850767 adapted configuration for DatatypeCase.make_case
bulwahn
parents: 32035
diff changeset
   267
fun gen_make_case ty_match ty_inst type_of tab ctxt config used x clauses =
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   268
  let
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   269
    fun string_of_clause (pat, rhs) =
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   270
      Syntax.string_of_term ctxt (Syntax.const @{syntax_const "_case1"} $ pat $ rhs);
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   271
    val _ = map (no_repeat_vars ctxt o fst) clauses;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   272
    val rows = map_index (fn (i, (pat, rhs)) =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   273
      (([], [pat]), (rhs, (i, true)))) clauses;
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   274
    val rangeT =
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   275
      (case distinct op = (map (type_of o snd) clauses) of
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   276
        [] => case_error "no clauses given"
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   277
      | [T] => T
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   278
      | _ => case_error "all cases must have the same result type");
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   279
    val used' = fold add_row_used rows used;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   280
    val (patts, case_tm) = mk_case tab ctxt ty_match ty_inst type_of
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   281
        used' rangeT {path = [x], rows = rows}
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   282
      handle CASE_ERROR (msg, i) => case_error (msg ^
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   283
        (if i < 0 then ""
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   284
         else "\nIn clause\n" ^ string_of_clause (nth clauses i)));
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   285
    val patts1 = map
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   286
      (fn (_, tag, [pat]) => (pat, tag)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   287
        | _ => case_error "error in pattern-match translation") patts;
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   288
    val patts2 = Library.sort (int_ord o pairself row_of_pat) patts1
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   289
    val finals = map row_of_pat patts2
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   290
    val originals = map (row_of_pat o #2) rows
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   291
    val _ =
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   292
        case subtract (op =) finals originals of
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   293
          [] => ()
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   294
        | is =>
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   295
            (case config of Error => case_error | Warning => warning | Quiet => fn _ => {})
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   296
              ("The following clauses are redundant (covered by preceding clauses):\n" ^
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   297
               cat_lines (map (string_of_clause o nth clauses) is));
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   298
  in
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   299
    (case_tm, patts2)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   300
  end;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   301
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   302
fun make_case tab ctxt = gen_make_case
32035
8e77b6a250d5 tuned/modernized Envir.subst_XXX;
wenzelm
parents: 31775
diff changeset
   303
  (match_type (ProofContext.theory_of ctxt)) Envir.subst_term_types fastype_of tab ctxt;
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   304
val make_case_untyped = gen_make_case (K (K Vartab.empty))
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   305
  (K (Term.map_types (K dummyT))) (K dummyT);
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   306
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   307
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   308
(* parse translation *)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   309
24349
0dd8782fb02d Final mods for list comprehension
nipkow
parents: 22779
diff changeset
   310
fun case_tr err tab_of ctxt [t, u] =
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   311
    let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   312
      val thy = ProofContext.theory_of ctxt;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   313
      (* replace occurrences of dummy_pattern by distinct variables *)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   314
      (* internalize constant names                                 *)
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   315
      fun prep_pat ((c as Const (@{syntax_const "_constrain"}, _)) $ t $ tT) used =
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   316
            let val (t', used') = prep_pat t used
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   317
            in (c $ t' $ tT, used') end
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   318
        | prep_pat (Const (@{const_name dummy_pattern}, T)) used =
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   319
            let val x = Name.variant used "x"
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   320
            in (Free (x, T), x :: used) end
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   321
        | prep_pat (Const (s, T)) used =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   322
            (case try (unprefix Syntax.constN) s of
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   323
               SOME c => (Const (c, T), used)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   324
             | NONE => (Const (Sign.intern_const thy s, T), used))
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   325
        | prep_pat (v as Free (s, T)) used =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   326
            let val s' = Sign.intern_const thy s
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   327
            in
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   328
              if Sign.declared_const thy s' then
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   329
                (Const (s', T), used)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   330
              else (v, used)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   331
            end
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   332
        | prep_pat (t $ u) used =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   333
            let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   334
              val (t', used') = prep_pat t used;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   335
              val (u', used'') = prep_pat u used'
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   336
            in
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   337
              (t' $ u', used'')
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   338
            end
24920
2a45e400fdad generic Syntax.pretty/string_of operations;
wenzelm
parents: 24349
diff changeset
   339
        | prep_pat t used = case_error ("Bad pattern: " ^ Syntax.string_of_term ctxt t);
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   340
      fun dest_case1 (t as Const (@{syntax_const "_case1"}, _) $ l $ r) =
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   341
            let val (l', cnstrts) = strip_constraints l
29281
b22ccb3998db eliminated OldTerm.add_term_free_names;
wenzelm
parents: 29270
diff changeset
   342
            in ((fst (prep_pat l' (Term.add_free_names t [])), r), cnstrts)
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   343
            end
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   344
        | dest_case1 t = case_error "dest_case1";
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   345
      fun dest_case2 (Const (@{syntax_const "_case2"}, _) $ t $ u) = t :: dest_case2 u
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   346
        | dest_case2 t = [t];
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   347
      val (cases, cnstrts) = split_list (map dest_case1 (dest_case2 u));
32671
fbd224850767 adapted configuration for DatatypeCase.make_case
bulwahn
parents: 32035
diff changeset
   348
      val (case_tm, _) = make_case_untyped (tab_of thy) ctxt
fbd224850767 adapted configuration for DatatypeCase.make_case
bulwahn
parents: 32035
diff changeset
   349
        (if err then Error else Warning) []
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   350
        (fold (fn tT => fn t => Syntax.const @{syntax_const "_constrain"} $ t $ tT)
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   351
           (flat cnstrts) t) cases;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   352
    in case_tm end
24349
0dd8782fb02d Final mods for list comprehension
nipkow
parents: 22779
diff changeset
   353
  | case_tr _ _ _ ts = case_error "case_tr";
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   354
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   355
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   356
(*---------------------------------------------------------------------------
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   357
 * Pretty printing of nested case expressions
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   358
 *---------------------------------------------------------------------------*)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   359
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   360
(* destruct one level of pattern matching *)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   361
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   362
fun gen_dest_case name_of type_of tab d used t =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   363
  case apfst name_of (strip_comb t) of
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   364
    (SOME cname, ts as _ :: _) =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   365
      let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   366
        val (fs, x) = split_last ts;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   367
        fun strip_abs i t =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   368
          let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   369
            val zs = strip_abs_vars t;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   370
            val _ = if length zs < i then raise CASE_ERROR ("", 0) else ();
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   371
            val (xs, ys) = chop i zs;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   372
            val u = list_abs (ys, strip_abs_body t);
29270
0eade173f77e moved old add_type_XXX, add_term_XXX etc. to structure OldTerm;
wenzelm
parents: 29266
diff changeset
   373
            val xs' = map Free (Name.variant_list (OldTerm.add_term_names (u, used))
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   374
              (map fst xs) ~~ map snd xs)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   375
          in (xs', subst_bounds (rev xs', u)) end;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   376
        fun is_dependent i t =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   377
          let val k = length (strip_abs_vars t) - i
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   378
          in k < 0 orelse exists (fn j => j >= k)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   379
            (loose_bnos (strip_abs_body t))
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   380
          end;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   381
        fun count_cases (_, _, true) = I
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   382
          | count_cases (c, (_, body), false) =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   383
              AList.map_default op aconv (body, []) (cons c);
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   384
        val is_undefined = name_of #> equal (SOME @{const_name HOL.undefined});
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   385
        fun mk_case (c, (xs, body), _) = (list_comb (c, xs), body)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   386
      in case ty_info tab cname of
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   387
          SOME {constructors, case_name} =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   388
            if length fs = length constructors then
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   389
              let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   390
                val cases = map (fn (Const (s, U), t) =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   391
                  let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   392
                    val k = length (binder_types U);
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   393
                    val p as (xs, _) = strip_abs k t
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   394
                  in
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   395
                    (Const (s, map type_of xs ---> type_of x),
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   396
                     p, is_dependent k t)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   397
                  end) (constructors ~~ fs);
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   398
                val cases' = sort (int_ord o swap o pairself (length o snd))
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   399
                  (fold_rev count_cases cases []);
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   400
                val R = type_of t;
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   401
                val dummy =
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   402
                  if d then Const (@{const_name dummy_pattern}, R)
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   403
                  else Free (Name.variant used "x", R)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   404
              in
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   405
                SOME (x, map mk_case (case find_first (is_undefined o fst) cases' of
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   406
                  SOME (_, cs) =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   407
                  if length cs = length constructors then [hd cases]
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   408
                  else filter_out (fn (_, (_, body), _) => is_undefined body) cases
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   409
                | NONE => case cases' of
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   410
                  [] => cases
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   411
                | (default, cs) :: _ =>
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   412
                  if length cs = 1 then cases
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   413
                  else if length cs = length constructors then
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   414
                    [hd cases, (dummy, ([], default), false)]
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   415
                  else
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   416
                    filter_out (fn (c, _, _) => member op aconv cs c) cases @
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   417
                    [(dummy, ([], default), false)]))
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   418
              end handle CASE_ERROR _ => NONE
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   419
            else NONE
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   420
        | _ => NONE
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   421
      end
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   422
  | _ => NONE;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   423
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   424
val dest_case = gen_dest_case (try (dest_Const #> fst)) fastype_of;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   425
val dest_case' = gen_dest_case
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   426
  (try (dest_Const #> fst #> unprefix Syntax.constN)) (K dummyT);
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   427
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   428
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   429
(* destruct nested patterns *)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   430
29623
1219985d24b5 avoiding misleading name duplicate
haftmann
parents: 29281
diff changeset
   431
fun strip_case'' dest (pat, rhs) =
29281
b22ccb3998db eliminated OldTerm.add_term_free_names;
wenzelm
parents: 29270
diff changeset
   432
  case dest (Term.add_free_names pat []) rhs of
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   433
    SOME (exp as Free _, clauses) =>
29266
4a478f9d2847 use regular Term.add_vars, Term.add_frees etc.;
wenzelm
parents: 26931
diff changeset
   434
      if member op aconv (OldTerm.term_frees pat) exp andalso
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   435
        not (exists (fn (_, rhs') =>
29266
4a478f9d2847 use regular Term.add_vars, Term.add_frees etc.;
wenzelm
parents: 26931
diff changeset
   436
          member op aconv (OldTerm.term_frees rhs') exp) clauses)
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   437
      then
29623
1219985d24b5 avoiding misleading name duplicate
haftmann
parents: 29281
diff changeset
   438
        maps (strip_case'' dest) (map (fn (pat', rhs') =>
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   439
          (subst_free [(exp, pat')] pat, rhs')) clauses)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   440
      else [(pat, rhs)]
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   441
  | _ => [(pat, rhs)];
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   442
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   443
fun gen_strip_case dest t =
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   444
  case dest [] t of
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   445
    SOME (x, clauses) =>
29623
1219985d24b5 avoiding misleading name duplicate
haftmann
parents: 29281
diff changeset
   446
      SOME (x, maps (strip_case'' dest) clauses)
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   447
  | NONE => NONE;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   448
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   449
val strip_case = gen_strip_case oo dest_case;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   450
val strip_case' = gen_strip_case oo dest_case';
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   451
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   452
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   453
(* print translation *)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   454
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   455
fun case_tr' tab_of cname ctxt ts =
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   456
  let
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   457
    val thy = ProofContext.theory_of ctxt;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   458
    val consts = ProofContext.consts_of ctxt;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   459
    fun mk_clause (pat, rhs) =
29266
4a478f9d2847 use regular Term.add_vars, Term.add_frees etc.;
wenzelm
parents: 26931
diff changeset
   460
      let val xs = Term.add_frees pat []
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   461
      in
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   462
        Syntax.const @{syntax_const "_case1"} $
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   463
          map_aterms
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   464
            (fn Free p => Syntax.mark_boundT p
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   465
              | Const (s, _) => Const (Consts.extern_early consts s, dummyT)
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   466
              | t => t) pat $
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   467
          map_aterms
29266
4a478f9d2847 use regular Term.add_vars, Term.add_frees etc.;
wenzelm
parents: 26931
diff changeset
   468
            (fn x as Free (s, T) =>
4a478f9d2847 use regular Term.add_vars, Term.add_frees etc.;
wenzelm
parents: 26931
diff changeset
   469
                  if member (op =) xs (s, T) then Syntax.mark_bound s else x
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   470
              | t => t) rhs
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   471
      end
35124
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   472
  in
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   473
    case strip_case' (tab_of thy) true (list_comb (Syntax.const cname, ts)) of
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   474
      SOME (x, clauses) =>
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   475
        Syntax.const @{syntax_const "_case_syntax"} $ x $
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   476
          foldr1 (fn (t, u) => Syntax.const @{syntax_const "_case2"} $ t $ u)
33976519c888 formal markup of constants;
wenzelm
parents: 33969
diff changeset
   477
            (map mk_clause clauses)
22779
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   478
    | NONE => raise Match
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   479
  end;
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   480
9ac0ca736969 Parse / print translations for nested case expressions, taken
berghofe
parents:
diff changeset
   481
end;