src/HOL/Library/case_converter.ML
author Andreas Lochbihler
Sat, 12 May 2018 11:24:11 +0200
changeset 68155 8b50f29a1992
child 68301 fb5653a7a879
permissions -rw-r--r--
new tool Code_Lazy
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
68155
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
     1
(* Author: Pascal Stoop, ETH Zurich
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
     2
   Author: Andreas Lochbihler, Digital Asset *)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
     3
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
     4
signature CASE_CONVERTER =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
     5
sig
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
     6
  val to_case: Proof.context -> (string * string -> bool) -> (string * typ -> int) ->
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
     7
    thm list -> thm list option
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
     8
end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
     9
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    10
structure Case_Converter : CASE_CONVERTER =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    11
struct
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    12
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    13
fun lookup_remove _ _ [] = (NONE, [])
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    14
  | lookup_remove eq k ((k', v) :: kvs) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    15
    if eq (k, k') then (SOME (k', v), kvs)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    16
    else apsnd (cons (k', v)) (lookup_remove eq k kvs)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    17
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    18
fun map_option _ NONE = NONE
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    19
  | map_option f (SOME x) = SOME (f x)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    20
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    21
fun mk_abort msg t =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    22
  let 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    23
    val T = fastype_of t
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    24
    val abort = Const (@{const_name missing_pattern_match}, HOLogic.literalT --> (HOLogic.unitT --> T) --> T)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    25
  in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    26
    abort $ HOLogic.mk_literal msg $ absdummy HOLogic.unitT t
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    27
  end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    28
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    29
(* fold_term : (string * typ -> 'a) ->
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    30
               (string * typ -> 'a) ->
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    31
               (indexname * typ -> 'a) ->
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    32
               (int -> 'a) ->
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    33
               (string * typ * 'a -> 'a) ->
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    34
               ('a * 'a -> 'a) ->
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    35
               term ->
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    36
               'a *)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    37
fun fold_term const_fun free_fun var_fun bound_fun abs_fun dollar_fun term =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    38
  let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    39
    fun go x = case x of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    40
      Const (s, T) => const_fun (s, T)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    41
      | Free (s, T) => free_fun (s, T)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    42
      | Var (i, T) => var_fun (i, T)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    43
      | Bound n => bound_fun n
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    44
      | Abs (s, T, term) => abs_fun (s, T, go term)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    45
      | term1 $ term2 => dollar_fun (go term1, go term2)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    46
  in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    47
    go term
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    48
  end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    49
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    50
datatype term_coordinate = End of typ
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    51
  | Coordinate of (string * (int * term_coordinate)) list;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    52
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    53
fun term_coordinate_merge (End T) _ = End T
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    54
  | term_coordinate_merge _ (End T) = End T
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    55
  | term_coordinate_merge (Coordinate xs) (Coordinate ys) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    56
  let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    57
    fun merge_consts xs [] = xs
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    58
      | merge_consts xs ((s1, (n, y)) :: ys) = 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    59
        case List.partition (fn (s2, (m, _)) => s1 = s2 andalso n = m) xs of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    60
            ([], xs') => (s1, (n, y)) :: (merge_consts xs' ys)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    61
          | ((_, (_, x)) :: _, xs') => (s1, (n, term_coordinate_merge x y)) :: (merge_consts xs' ys)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    62
  in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    63
    Coordinate (merge_consts xs ys)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    64
  end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    65
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    66
fun term_to_coordinates P term = 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    67
  let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    68
    val (ctr, args) = strip_comb term
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    69
  in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    70
    case ctr of Const (s, T) =>
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    71
      if P (body_type T |> dest_Type |> fst, s)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    72
      then SOME (End (body_type T))
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    73
      else
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    74
        let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    75
          fun f (i, t) = term_to_coordinates P t |> map_option (pair i)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    76
          val tcos = map_filter I (map_index f args)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    77
        in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    78
          if null tcos then NONE
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    79
          else SOME (Coordinate (map (pair s) tcos))
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    80
        end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    81
    | _ => NONE
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    82
  end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    83
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    84
fun coordinates_to_list (End x) = [(x, [])]
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    85
  | coordinates_to_list (Coordinate xs) = 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    86
  let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    87
    fun f (s, (n, xss)) = map (fn (T, xs) => (T, (s, n) :: xs)) (coordinates_to_list xss)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    88
  in flat (map f xs) end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    89
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    90
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    91
(* AL: TODO: change from term to const_name *)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    92
fun find_ctr ctr1 xs =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    93
  let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    94
    val const_name = fst o dest_Const
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    95
    fun const_equal (ctr1, ctr2) = const_name ctr1 = const_name ctr2
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    96
  in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    97
    lookup_remove const_equal ctr1 xs
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    98
  end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
    99
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   100
datatype pattern 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   101
  = Wildcard
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   102
  | Value
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   103
  | Split of int * (term * pattern) list * pattern;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   104
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   105
fun pattern_merge Wildcard pat' = pat'
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   106
  | pattern_merge Value _ = Value
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   107
  | pattern_merge (Split (n, xs, pat)) Wildcard =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   108
    Split (n, map (apsnd (fn pat'' => pattern_merge pat'' Wildcard)) xs, pattern_merge pat Wildcard)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   109
  | pattern_merge (Split _) Value = Value
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   110
  | pattern_merge (Split (n, xs, pat)) (Split (m, ys, pat'')) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   111
    let 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   112
      fun merge_consts xs [] = map (apsnd (fn pat => pattern_merge pat Wildcard)) xs
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   113
        | merge_consts xs ((ctr, y) :: ys) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   114
          (case find_ctr ctr xs of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   115
              (SOME (ctr, x), xs) => (ctr, pattern_merge x y) :: merge_consts xs ys
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   116
            | (NONE, xs) => (ctr, y) :: merge_consts xs ys
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   117
          )
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   118
     in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   119
       Split (if n <= 0 then m else n, merge_consts xs ys, pattern_merge pat pat'')
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   120
     end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   121
     
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   122
fun pattern_intersect Wildcard _ = Wildcard
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   123
  | pattern_intersect Value pat2 = pat2
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   124
  | pattern_intersect (Split _) Wildcard = Wildcard
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   125
  | pattern_intersect (Split (n, xs', pat1)) Value =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   126
    Split (n,
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   127
      map (apsnd (fn pat1 => pattern_intersect pat1 Value)) xs',
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   128
      pattern_intersect pat1 Value)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   129
  | pattern_intersect (Split (n, xs', pat1)) (Split (m, ys, pat2)) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   130
    Split (if n <= 0 then m else n, 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   131
      intersect_consts xs' ys pat1 pat2,
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   132
      pattern_intersect pat1 pat2)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   133
and
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   134
    intersect_consts xs [] _ default2 = map (apsnd (fn pat => pattern_intersect pat default2)) xs
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   135
  | intersect_consts xs ((ctr, pat2) :: ys) default1 default2 = case find_ctr ctr xs of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   136
    (SOME (ctr, pat1), xs') => 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   137
      (ctr, pattern_merge (pattern_merge (pattern_intersect pat1 pat2) (pattern_intersect default1 pat2))
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   138
              (pattern_intersect pat1 default2)) ::
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   139
      intersect_consts xs' ys default1 default2
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   140
    | (NONE, xs') => (ctr, pattern_intersect default1 pat2) :: (intersect_consts xs' ys default1 default2)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   141
        
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   142
fun pattern_lookup _ Wildcard = Wildcard
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   143
  | pattern_lookup _ Value = Value
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   144
  | pattern_lookup [] (Split (n, xs, pat)) = 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   145
    Split (n, map (apsnd (pattern_lookup [])) xs, pattern_lookup [] pat)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   146
  | pattern_lookup (term :: terms) (Split (n, xs, pat)) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   147
  let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   148
    val (ctr, args) = strip_comb term
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   149
    fun map_ctr (term, pat) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   150
      let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   151
        val args = term |> dest_Const |> snd |> binder_types |> map (fn T => Free ("x", T))
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   152
      in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   153
        pattern_lookup args pat
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   154
      end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   155
  in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   156
    if is_Const ctr then
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   157
       case find_ctr ctr xs of (SOME (_, pat'), _) => 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   158
           pattern_lookup terms (pattern_merge (pattern_lookup args pat') (pattern_lookup [] pat))
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   159
         | (NONE, _) => pattern_lookup terms pat
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   160
    else if length xs < n orelse n <= 0 then
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   161
      pattern_lookup terms pat
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   162
    else pattern_lookup terms
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   163
      (pattern_merge
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   164
        (fold pattern_intersect (map map_ctr (tl xs)) (map_ctr (hd xs)))
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   165
        (pattern_lookup [] pat))
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   166
  end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   167
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   168
fun pattern_contains terms pat = case pattern_lookup terms pat of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   169
    Wildcard => false
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   170
  | Value => true
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   171
  | Split _ => raise Match;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   172
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   173
fun pattern_create _ [] = Wildcard
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   174
  | pattern_create ctr_count (term :: terms) = 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   175
    let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   176
      val (ctr, args) = strip_comb term
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   177
    in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   178
      if is_Const ctr then
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   179
        Split (ctr_count ctr, [(ctr, pattern_create ctr_count (args @ terms))], Wildcard)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   180
      else Split (0, [], pattern_create ctr_count terms)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   181
    end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   182
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   183
fun pattern_insert ctr_count terms pat =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   184
  let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   185
    fun new_pattern terms = pattern_insert ctr_count terms (pattern_create ctr_count terms)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   186
    fun aux _ false Wildcard = Wildcard
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   187
      | aux terms true Wildcard = if null terms then Value else new_pattern terms
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   188
      | aux _ _ Value = Value
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   189
      | aux terms modify (Split (n, xs', pat)) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   190
      let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   191
        val unmodified = (n, map (apsnd (aux [] false)) xs', aux [] false pat)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   192
      in case terms of [] => Split unmodified
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   193
        | term :: terms =>
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   194
        let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   195
          val (ctr, args) = strip_comb term
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   196
          val (m, ys, pat') = unmodified
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   197
        in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   198
          if is_Const ctr
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   199
            then case find_ctr ctr xs' of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   200
              (SOME (ctr, pat''), xs) =>
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   201
                Split (m, (ctr, aux (args @ terms) modify pat'') :: map (apsnd (aux [] false)) xs, pat')
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   202
              | (NONE, _) => if modify
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   203
                then if m <= 0
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   204
                  then Split (ctr_count ctr, (ctr, new_pattern (args @ terms)) :: ys, pat')
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   205
                  else Split (m, (ctr, new_pattern (args @ terms)) :: ys, pat')
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   206
                else Split unmodified
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   207
            else Split (m, ys, aux terms modify pat)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   208
        end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   209
      end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   210
  in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   211
    aux terms true pat
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   212
  end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   213
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   214
val pattern_empty = Wildcard;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   215
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   216
fun replace_frees lhss rhss typ_list ctxt =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   217
  let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   218
    fun replace_frees_once (lhs, rhs) ctxt =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   219
      let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   220
        val add_frees_list = fold_rev Term.add_frees
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   221
        val frees = add_frees_list lhs []
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   222
        val (new_frees, ctxt1) = (Ctr_Sugar_Util.mk_Frees "x" (map snd frees) ctxt)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   223
        val (new_frees1, ctxt2) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   224
          let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   225
            val (dest_frees, types) = split_list (map dest_Free new_frees)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   226
            val (new_frees, ctxt2) = Variable.variant_fixes dest_frees ctxt1
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   227
          in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   228
            (map Free (new_frees ~~ types), ctxt2)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   229
          end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   230
        val dict = frees ~~ new_frees1
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   231
        fun free_map_fun (s, T) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   232
          case AList.lookup (op =) dict (s, T) of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   233
              NONE => Free (s, T)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   234
            | SOME x => x
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   235
        val map_fun = fold_term Const free_map_fun Var Bound Abs (op $)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   236
      in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   237
        ((map map_fun lhs, map_fun rhs), ctxt2)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   238
      end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   239
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   240
    fun variant_fixes (def_frees, ctxt) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   241
      let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   242
        val (dest_frees, types) = split_list (map dest_Free def_frees)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   243
        val (def_frees, ctxt1) = Variable.variant_fixes dest_frees ctxt
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   244
      in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   245
        (map Free (def_frees ~~ types), ctxt1)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   246
      end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   247
    val (def_frees, ctxt1) = variant_fixes (Ctr_Sugar_Util.mk_Frees "x" typ_list ctxt)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   248
    val (rhs_frees, ctxt2) = variant_fixes (Ctr_Sugar_Util.mk_Frees "x" typ_list ctxt1)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   249
    val (case_args, ctxt3) = variant_fixes (Ctr_Sugar_Util.mk_Frees "x"
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   250
      (map fastype_of (hd lhss)) ctxt2)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   251
    val (new_terms1, ctxt4) = fold_map replace_frees_once (lhss ~~ rhss) ctxt3
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   252
    val (lhss1, rhss1) = split_list new_terms1
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   253
  in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   254
    (lhss1, rhss1, def_frees ~~ rhs_frees, case_args, ctxt4)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   255
  end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   256
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   257
fun add_names_in_type (Type (name, Ts)) = 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   258
    List.foldr (op o) (Symtab.update (name, ())) (map add_names_in_type Ts)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   259
  | add_names_in_type (TFree _) = I
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   260
  | add_names_in_type (TVar _) = I
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   261
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   262
fun add_names_in_term (Const (_, T)) = add_names_in_type T
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   263
  | add_names_in_term (Free (_, T)) = add_names_in_type T
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   264
  | add_names_in_term (Var (_, T)) = add_names_in_type T
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   265
  | add_names_in_term (Bound _) = I
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   266
  | add_names_in_term (Abs (_, T, body)) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   267
    add_names_in_type T o add_names_in_term body
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   268
  | add_names_in_term (t1 $ t2) = add_names_in_term t1 o add_names_in_term t2
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   269
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   270
fun add_type_names terms =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   271
  fold (fn term => fn f => add_names_in_term term o f) terms I
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   272
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   273
fun get_split_theorems ctxt =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   274
  Symtab.keys
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   275
  #> map_filter (Ctr_Sugar.ctr_sugar_of ctxt)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   276
  #> map #split;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   277
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   278
fun match (Const (s1, _)) (Const (s2, _)) = if s1 = s2 then SOME I else NONE
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   279
  | match (Free y) x = SOME (fn z => if z = Free y then x else z)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   280
  | match (pat1 $ pattern2) (t1 $ t2) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   281
    (case (match pat1 t1, match pattern2 t2) of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   282
       (SOME f, SOME g) => SOME (f o g)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   283
       | _ => NONE
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   284
     )
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   285
  | match _ _ = NONE;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   286
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   287
fun match_all patterns terms =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   288
  let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   289
    fun combine _ NONE = NONE
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   290
      | combine (f_opt, f_opt') (SOME g) = 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   291
        case match f_opt f_opt' of SOME f => SOME (f o g) | _ => NONE
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   292
  in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   293
    fold_rev combine (patterns ~~ terms) (SOME I)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   294
  end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   295
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   296
fun matches (Const (s1, _)) (Const (s2, _)) = s1 = s2
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   297
  | matches (Free _) _ = true 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   298
  | matches (pat1 $ pat2) (t1 $ t2) = matches pat1 t1 andalso matches pat2 t2
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   299
  | matches _ _ = false;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   300
fun matches_all patterns terms = forall (uncurry matches) (patterns ~~ terms)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   301
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   302
fun terms_to_case_at ctr_count ctxt (fun_t : term) (default_lhs : term list)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   303
    (pos, (lazy_case_arg, rhs_free))
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   304
    ((lhss : term list list), (rhss : term list), type_name_fun) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   305
  let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   306
    fun abort t =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   307
      let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   308
        val fun_name = head_of t |> dest_Const |> fst
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   309
        val msg = "Missing pattern in " ^ fun_name ^ "."
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   310
      in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   311
        mk_abort msg t
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   312
      end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   313
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   314
    (* Step 1 : Eliminate lazy pattern *)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   315
    fun replace_pat_at (n, tcos) pat pats =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   316
      let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   317
        fun map_at _ _ [] = raise Empty
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   318
          | map_at n f (x :: xs) = if n > 0
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   319
            then apfst (cons x) (map_at (n - 1) f xs)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   320
            else apfst (fn x => x :: xs) (f x)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   321
        fun replace [] pat term = (pat, term)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   322
          | replace ((s1, n) :: tcos) pat term =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   323
            let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   324
              val (ctr, args) = strip_comb term
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   325
            in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   326
              case ctr of Const (s2, _) =>
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   327
                  if s1 = s2
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   328
                  then apfst (pair ctr #> list_comb) (map_at n (replace tcos pat) args)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   329
                  else (term, rhs_free)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   330
                | _ => (term, rhs_free)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   331
            end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   332
        val (part1, (old_pat, part2)) = chop n pats ||> (fn xs => (hd xs, tl xs))
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   333
        val (new_pat, old_pat1) = replace tcos pat old_pat
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   334
      in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   335
        (part1 @ [new_pat] @ part2, old_pat1)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   336
      end                               
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   337
    val (lhss1, lazy_pats) = map (replace_pat_at pos lazy_case_arg) lhss
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   338
      |> split_list
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   339
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   340
    (* Step 2 : Split patterns *)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   341
    fun split equs =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   342
      let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   343
        fun merge_pattern (Const (s1, T1), Const (s2, _)) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   344
            if s1 = s2 then SOME (Const (s1, T1)) else NONE
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   345
          | merge_pattern (t, Free _) = SOME t
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   346
          | merge_pattern (Free _, t) = SOME t
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   347
          | merge_pattern (t1l $ t1r, t2l $ t2r) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   348
            (case (merge_pattern (t1l, t2l), merge_pattern (t1r, t2r)) of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   349
              (SOME t1, SOME t2) => SOME (t1 $ t2)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   350
              | _ => NONE)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   351
          | merge_pattern _ = NONE
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   352
        fun merge_patterns pats1 pats2 = case (pats1, pats2) of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   353
          ([], []) => SOME []
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   354
          | (x :: xs, y :: ys) =>
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   355
            (case (merge_pattern (x, y), merge_patterns xs ys) of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   356
              (SOME x, SOME xs) => SOME (x :: xs)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   357
              | _ => NONE
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   358
            )
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   359
          | _ => raise Match
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   360
        fun merge_insert ((lhs1, case_pat), _) [] =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   361
            [(lhs1, pattern_empty |> pattern_insert ctr_count [case_pat])]
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   362
          | merge_insert ((lhs1, case_pat), rhs) ((lhs2, pat) :: pats) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   363
            let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   364
              val pats = merge_insert ((lhs1, case_pat), rhs) pats
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   365
              val (first_equ_needed, new_lhs) = case merge_patterns lhs1 lhs2 of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   366
                SOME new_lhs => (not (pattern_contains [case_pat] pat), new_lhs)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   367
                | NONE => (false, lhs2)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   368
              val second_equ_needed = not (matches_all lhs1 lhs2)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   369
                orelse not first_equ_needed
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   370
              val first_equ = if first_equ_needed
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   371
                then [(new_lhs, pattern_insert ctr_count [case_pat] pat)]
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   372
                else []
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   373
              val second_equ = if second_equ_needed
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   374
                then [(lhs2, pat)]
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   375
                else []
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   376
            in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   377
              first_equ @ second_equ @ pats
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   378
            end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   379
        in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   380
          (fold merge_insert equs []
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   381
            |> split_list
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   382
            |> fst) @ [default_lhs]
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   383
        end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   384
    val lhss2 = split ((lhss1 ~~ lazy_pats) ~~ rhss)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   385
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   386
    (* Step 3 : Remove redundant patterns *)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   387
    fun remove_redundant_lhs lhss =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   388
      let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   389
        fun f lhs pat = if pattern_contains lhs pat
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   390
          then ((lhs, false), pat)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   391
          else ((lhs, true), pattern_insert ctr_count lhs pat)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   392
      in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   393
        fold_map f lhss pattern_empty
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   394
        |> fst
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   395
        |> filter snd
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   396
        |> map fst
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   397
      end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   398
    fun remove_redundant_rhs rhss =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   399
      let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   400
        fun f (lhs, rhs) pat = if pattern_contains [lhs] pat
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   401
          then (((lhs, rhs), false), pat)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   402
          else (((lhs, rhs), true), pattern_insert ctr_count [lhs] pat)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   403
      in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   404
        map fst (filter snd (fold_map f rhss pattern_empty |> fst))
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   405
      end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   406
    val lhss3 = remove_redundant_lhs lhss2
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   407
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   408
    (* Step 4 : Compute right hand side *)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   409
    fun subs_fun f = fold_term
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   410
      Const
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   411
      (f o Free)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   412
      Var
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   413
      Bound
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   414
      Abs
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   415
      (fn (x, y) => f x $ f y)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   416
    fun find_rhss lhs =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   417
      let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   418
        fun f (lhs1, (pat, rhs)) = 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   419
          case match_all lhs1 lhs of NONE => NONE
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   420
          | SOME f => SOME (pat, subs_fun f rhs)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   421
      in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   422
        remove_redundant_rhs
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   423
          (map_filter f (lhss1 ~~ (lazy_pats ~~ rhss)) @
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   424
            [(lazy_case_arg, list_comb (fun_t, lhs) |> abort)]
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   425
          )
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   426
      end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   427
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   428
    (* Step 5 : make_case of right hand side *)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   429
    fun make_case ctxt case_arg cases = case cases of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   430
      [(Free x, rhs)] => subs_fun (fn y => if y = Free x then case_arg else y) rhs
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   431
      | _ => Case_Translation.make_case
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   432
        ctxt
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   433
        Case_Translation.Warning
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   434
        Name.context
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   435
        case_arg
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   436
        cases
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   437
    val type_name_fun = add_type_names lazy_pats o type_name_fun
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   438
    val rhss3 = map ((make_case ctxt lazy_case_arg) o find_rhss) lhss3
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   439
  in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   440
    (lhss3, rhss3, type_name_fun)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   441
  end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   442
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   443
fun terms_to_case ctxt ctr_count (head : term) (lhss : term list list)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   444
    (rhss : term list) (typ_list : typ list) (poss : (int * (string * int) list) list) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   445
  let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   446
    val (lhss1, rhss1, def_frees, case_args, ctxt1) = replace_frees lhss rhss typ_list ctxt
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   447
    val exec_list = poss ~~ def_frees
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   448
    val (lhss2, rhss2, type_name_fun) = fold_rev
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   449
      (terms_to_case_at ctr_count ctxt1 head case_args) exec_list (lhss1, rhss1, I)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   450
    fun make_eq_term (lhss, rhs) = (list_comb (head, lhss), rhs)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   451
      |> HOLogic.mk_eq
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   452
      |> HOLogic.mk_Trueprop
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   453
  in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   454
    (map make_eq_term (lhss2 ~~ rhss2),
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   455
      get_split_theorems ctxt1 (type_name_fun Symtab.empty),
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   456
      ctxt1)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   457
  end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   458
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   459
fun build_case_t replace_ctr ctr_count head lhss rhss ctxt =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   460
  let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   461
    val num_eqs = length lhss
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   462
    val _ = if length rhss = num_eqs andalso num_eqs > 0 then ()
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   463
      else raise Fail
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   464
        ("expected same number of left-hand sides as right-hand sides\n"
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   465
          ^ "and at least one equation")
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   466
    val n = length (hd lhss)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   467
    val _ = if forall (fn m => length m = n) lhss then ()
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   468
      else raise Fail "expected equal number of arguments"
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   469
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   470
    fun to_coordinates (n, ts) = case map_filter (term_to_coordinates replace_ctr) ts of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   471
        [] => NONE
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   472
      | (tco :: tcos) => SOME (n, fold term_coordinate_merge tcos tco |> coordinates_to_list)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   473
    fun add_T (n, xss) = map (fn (T, xs) => (T, (n, xs))) xss
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   474
    val (typ_list, poss) = lhss
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   475
      |> Ctr_Sugar_Util.transpose
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   476
      |> map_index to_coordinates
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   477
      |> map_filter (map_option add_T)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   478
      |> flat
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   479
      |> split_list 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   480
  in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   481
    if null poss then ([], [], ctxt)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   482
    else terms_to_case ctxt (dest_Const #> ctr_count) head lhss rhss typ_list poss
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   483
  end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   484
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   485
fun tac ctxt {splits, intros, defs} =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   486
  let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   487
    val split_and_subst = 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   488
      split_tac ctxt splits 
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   489
      THEN' REPEAT_ALL_NEW (
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   490
        resolve_tac ctxt [@{thm conjI}, @{thm allI}]
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   491
        ORELSE'
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   492
        (resolve_tac ctxt [@{thm impI}] THEN' hyp_subst_tac_thin true ctxt))
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   493
  in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   494
    (REPEAT_ALL_NEW split_and_subst ORELSE' K all_tac)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   495
    THEN' (K (Local_Defs.unfold_tac ctxt [@{thm missing_pattern_match_def}]))
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   496
    THEN' (K (Local_Defs.unfold_tac ctxt defs))
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   497
    THEN_ALL_NEW (SOLVED' (resolve_tac ctxt (@{thm refl} :: intros)))
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   498
  end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   499
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   500
fun to_case _ _ _ [] = NONE
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   501
  | to_case ctxt replace_ctr ctr_count ths =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   502
    let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   503
      val strip_eq = Thm.prop_of #> HOLogic.dest_Trueprop #> HOLogic.dest_eq
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   504
      fun import [] ctxt = ([], ctxt)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   505
        | import (thm :: thms) ctxt =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   506
          let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   507
            val fun_ct = strip_eq #> fst #> head_of #> Logic.mk_term #> Thm.cterm_of ctxt
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   508
            val ct = fun_ct thm
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   509
            val cts = map fun_ct thms
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   510
            val pairs = map (fn s => (s,ct)) cts
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   511
            val thms' = map (fn (th,p) => Thm.instantiate (Thm.match p) th) (thms ~~ pairs)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   512
          in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   513
            Variable.import true (thm :: thms') ctxt |> apfst snd
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   514
          end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   515
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   516
      val (iths, ctxt') = import ths ctxt
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   517
      val head = hd iths |> strip_eq |> fst |> head_of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   518
      val eqs = map (strip_eq #> apfst (snd o strip_comb)) iths
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   519
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   520
      fun hide_rhs ((pat, rhs), name) lthy =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   521
        let
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   522
          val frees = fold Term.add_frees pat []
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   523
          val abs_rhs = fold absfree frees rhs
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   524
          val (f, def, lthy') = case lthy
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   525
            |> Local_Defs.define [((Binding.name name, NoSyn), (Binding.empty_atts, abs_rhs))] of
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   526
              ([(f, (_, def))], lthy') => (f, def, lthy')
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   527
              | _ => raise Match
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   528
        in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   529
          ((list_comb (f, map Free (rev frees)), def), lthy')
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   530
        end
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   531
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   532
      val rhs_names = Name.invent (Variable.names_of ctxt') "rhs" (length eqs)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   533
      val ((def_ts, def_thms), ctxt2) =
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   534
        fold_map hide_rhs (eqs ~~ rhs_names) ctxt' |> apfst split_list
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   535
      val (ts, split_thms, ctxt3) = build_case_t replace_ctr ctr_count head
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   536
        (map fst eqs) def_ts ctxt2
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   537
      fun mk_thm t = Goal.prove ctxt3 [] [] t
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   538
          (fn {context=ctxt, ...} => tac ctxt {splits=split_thms, intros=ths, defs=def_thms} 1)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   539
    in
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   540
      if null ts then NONE
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   541
      else
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   542
        ts
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   543
        |> map mk_thm
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   544
        |> Proof_Context.export ctxt3 ctxt
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   545
        |> map (Goal.norm_result ctxt)
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   546
        |> SOME
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   547
    end;
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   548
8b50f29a1992 new tool Code_Lazy
Andreas Lochbihler
parents:
diff changeset
   549
end