src/HOL/BNF/Tools/bnf_fp_rec_sugar.ML
author traytel
Thu, 12 Sep 2013 16:58:22 +0200
changeset 53567 7f84e5e7a49b
parent 53411 ab4edf89992f
child 53654 8b9ea4420f81
permissions -rw-r--r--
buffer the notes even more
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
     1
(*  Title:      HOL/BNF/Tools/bnf_fp_rec_sugar.ML
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
     2
    Author:     Lorenz Panny, TU Muenchen
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
     3
    Copyright   2013
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
     4
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
     5
Recursor and corecursor sugar.
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
     6
*)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
     7
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
     8
signature BNF_FP_REC_SUGAR =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
     9
sig
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    10
  val add_primrec_cmd: (binding * string option * mixfix) list ->
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    11
    (Attrib.binding * string) list -> local_theory -> local_theory;
53310
8af01463b2d3 moved keywords down the hierarchy
blanchet
parents: 53304
diff changeset
    12
  val add_primcorec_cmd: bool ->
8af01463b2d3 moved keywords down the hierarchy
blanchet
parents: 53304
diff changeset
    13
    (binding * string option * mixfix) list * (Attrib.binding * string) list -> Proof.context ->
8af01463b2d3 moved keywords down the hierarchy
blanchet
parents: 53304
diff changeset
    14
    Proof.state
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    15
end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    16
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    17
structure BNF_FP_Rec_Sugar : BNF_FP_REC_SUGAR =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    18
struct
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    19
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    20
open BNF_Util
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    21
open BNF_FP_Util
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    22
open BNF_FP_Rec_Sugar_Util
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    23
open BNF_FP_Rec_Sugar_Tactics
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    24
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    25
exception Primrec_Error of string * term list;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    26
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    27
fun primrec_error str = raise Primrec_Error (str, []);
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    28
fun primrec_error_eqn str eqn = raise Primrec_Error (str, [eqn]);
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    29
fun primrec_error_eqns str eqns = raise Primrec_Error (str, eqns);
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    30
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
    31
fun finds eq = fold_map (fn x => List.partition (curry eq x) #>> pair x);
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
    32
53357
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
    33
val free_name = try (fn Free (v, _) => v);
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
    34
val const_name = try (fn Const (v, _) => v);
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
    35
val undef_const = Const (@{const_name undefined}, dummyT);
53357
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
    36
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
    37
fun permute_args n t = list_comb (t, map Bound (0 :: (n downto 1)))
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
    38
  |> fold (K (fn u => Abs (Name.uu, dummyT, u))) (0 upto n);
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
    39
val abs_tuple = HOLogic.tupled_lambda o HOLogic.mk_tuple;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    40
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    41
val simp_attrs = @{attributes [simp]};
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    42
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    43
53310
8af01463b2d3 moved keywords down the hierarchy
blanchet
parents: 53304
diff changeset
    44
8af01463b2d3 moved keywords down the hierarchy
blanchet
parents: 53304
diff changeset
    45
(* Primrec *)
8af01463b2d3 moved keywords down the hierarchy
blanchet
parents: 53304
diff changeset
    46
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    47
type eqn_data = {
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    48
  fun_name: string,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    49
  rec_type: typ,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    50
  ctr: term,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    51
  ctr_args: term list,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    52
  left_args: term list,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    53
  right_args: term list,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    54
  res_type: typ,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    55
  rhs_term: term,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    56
  user_eqn: term
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    57
};
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    58
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    59
fun dissect_eqn lthy fun_names eqn' =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    60
  let
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    61
    val eqn = subst_bounds (strip_qnt_vars @{const_name all} eqn' |> map Free |> rev,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    62
        strip_qnt_body @{const_name all} eqn') |> HOLogic.dest_Trueprop
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    63
        handle TERM _ =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    64
          primrec_error_eqn "malformed function equation (expected \"lhs = rhs\")" eqn';
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    65
    val (lhs, rhs) = HOLogic.dest_eq eqn
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    66
        handle TERM _ =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    67
          primrec_error_eqn "malformed function equation (expected \"lhs = rhs\")" eqn';
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    68
    val (fun_name, args) = strip_comb lhs
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    69
      |>> (fn x => if is_Free x then fst (dest_Free x)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    70
          else primrec_error_eqn "malformed function equation (does not start with free)" eqn);
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    71
    val (left_args, rest) = take_prefix is_Free args;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    72
    val (nonfrees, right_args) = take_suffix is_Free rest;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    73
    val _ = length nonfrees = 1 orelse if length nonfrees = 0 then
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    74
      primrec_error_eqn "constructor pattern missing in left-hand side" eqn else
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    75
      primrec_error_eqn "more than one non-variable argument in left-hand side" eqn;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    76
    val _ = member (op =) fun_names fun_name orelse
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    77
      primrec_error_eqn "malformed function equation (does not start with function name)" eqn
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    78
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    79
    val (ctr, ctr_args) = strip_comb (the_single nonfrees);
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    80
    val _ = try (num_binder_types o fastype_of) ctr = SOME (length ctr_args) orelse
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    81
      primrec_error_eqn "partially applied constructor in pattern" eqn;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    82
    val _ = let val d = duplicates (op =) (left_args @ ctr_args @ right_args) in null d orelse
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    83
      primrec_error_eqn ("duplicate variable \"" ^ Syntax.string_of_term lthy (hd d) ^
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    84
        "\" in left-hand side") eqn end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    85
    val _ = forall is_Free ctr_args orelse
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    86
      primrec_error_eqn "non-primitive pattern in left-hand side" eqn;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    87
    val _ =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    88
      let val b = fold_aterms (fn x as Free (v, _) =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    89
        if (not (member (op =) (left_args @ ctr_args @ right_args) x) andalso
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    90
        not (member (op =) fun_names v) andalso
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    91
        not (Variable.is_fixed lthy v)) then cons x else I | _ => I) rhs []
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    92
      in
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    93
        null b orelse
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    94
        primrec_error_eqn ("extra variable(s) in right-hand side: " ^
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    95
          commas (map (Syntax.string_of_term lthy) b)) eqn
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    96
      end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    97
  in
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    98
    {fun_name = fun_name,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
    99
     rec_type = body_type (type_of ctr),
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   100
     ctr = ctr,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   101
     ctr_args = ctr_args,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   102
     left_args = left_args,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   103
     right_args = right_args,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   104
     res_type = map fastype_of (left_args @ right_args) ---> fastype_of rhs,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   105
     rhs_term = rhs,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   106
     user_eqn = eqn'}
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   107
  end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   108
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   109
fun rewrite_map_arg get_ctr_pos rec_type res_type =
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   110
  let
53357
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   111
    val pT = HOLogic.mk_prodT (rec_type, res_type);
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   112
53357
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   113
    val maybe_suc = Option.map (fn x => x + 1);
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   114
    fun subst d (t as Bound d') = t |> d = SOME d' ? curry (op $) (fst_const pT)
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   115
      | subst d (Abs (v, T, b)) = Abs (v, if d = SOME ~1 then pT else T, subst (maybe_suc d) b)
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   116
      | subst d t =
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   117
        let
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   118
          val (u, vs) = strip_comb t;
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   119
          val ctr_pos = try (get_ctr_pos o the) (free_name u) |> the_default ~1;
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   120
        in
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   121
          if ctr_pos >= 0 then
53357
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   122
            if d = SOME ~1 andalso length vs = ctr_pos then
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   123
              list_comb (permute_args ctr_pos (snd_const pT), vs)
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   124
            else if length vs > ctr_pos andalso is_some d
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   125
                andalso d = try (fn Bound n => n) (nth vs ctr_pos) then
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   126
              list_comb (snd_const pT $ nth vs ctr_pos, map (subst d) (nth_drop ctr_pos vs))
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   127
            else
53357
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   128
              primrec_error_eqn ("recursive call not directly applied to constructor argument") t
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   129
          else if d = SOME ~1 andalso const_name u = SOME @{const_name comp} then
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   130
            list_comb (map_types (K dummyT) u, map2 subst [NONE, d] vs)
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   131
          else
53357
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   132
            list_comb (u, map (subst (d |> d = SOME ~1 ? K NONE)) vs)
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   133
        end
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   134
  in
53357
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   135
    subst (SOME ~1)
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   136
  end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   137
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   138
fun subst_rec_calls lthy get_ctr_pos has_call ctr_args direct_calls indirect_calls t =
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   139
  let
53350
17632ef6cfe8 simplified recursive calls' replacement
panny
parents: 53341
diff changeset
   140
    fun subst bound_Ts (Abs (v, T, b)) = Abs (v, T, subst (T :: bound_Ts) b)
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   141
      | subst bound_Ts (t as g' $ y) =
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   142
        let
53350
17632ef6cfe8 simplified recursive calls' replacement
panny
parents: 53341
diff changeset
   143
          val maybe_direct_y' = AList.lookup (op =) direct_calls y;
17632ef6cfe8 simplified recursive calls' replacement
panny
parents: 53341
diff changeset
   144
          val maybe_indirect_y' = AList.lookup (op =) indirect_calls y;
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   145
          val (g, g_args) = strip_comb g';
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   146
          val ctr_pos = try (get_ctr_pos o the) (free_name g) |> the_default ~1;
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   147
          val _ = ctr_pos < 0 orelse length g_args >= ctr_pos orelse
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   148
            primrec_error_eqn "too few arguments in recursive call" t;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   149
        in
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   150
          if not (member (op =) ctr_args y) then
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   151
            pairself (subst bound_Ts) (g', y) |> (op $)
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   152
          else if ctr_pos >= 0 then
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   153
            list_comb (the maybe_direct_y', g_args)
53350
17632ef6cfe8 simplified recursive calls' replacement
panny
parents: 53341
diff changeset
   154
          else if is_some maybe_indirect_y' then
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   155
            (if has_call g' then t else y)
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   156
            |> massage_indirect_rec_call lthy has_call
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   157
              (rewrite_map_arg get_ctr_pos) bound_Ts y (the maybe_indirect_y')
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   158
            |> (if has_call g' then I else curry (op $) g')
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   159
          else
53350
17632ef6cfe8 simplified recursive calls' replacement
panny
parents: 53341
diff changeset
   160
            t
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   161
        end
53350
17632ef6cfe8 simplified recursive calls' replacement
panny
parents: 53341
diff changeset
   162
      | subst _ t = t
17632ef6cfe8 simplified recursive calls' replacement
panny
parents: 53341
diff changeset
   163
  in
17632ef6cfe8 simplified recursive calls' replacement
panny
parents: 53341
diff changeset
   164
    subst [] t
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   165
    |> tap (fn u => has_call u andalso (* FIXME detect this case earlier *)
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   166
      primrec_error_eqn "recursive call not directly applied to constructor argument" t)
53350
17632ef6cfe8 simplified recursive calls' replacement
panny
parents: 53341
diff changeset
   167
  end;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   168
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   169
fun build_rec_arg lthy funs_data has_call ctr_spec maybe_eqn_data =
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   170
  if is_none maybe_eqn_data then undef_const else
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   171
    let
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   172
      val eqn_data = the maybe_eqn_data;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   173
      val t = #rhs_term eqn_data;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   174
      val ctr_args = #ctr_args eqn_data;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   175
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   176
      val calls = #calls ctr_spec;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   177
      val n_args = fold (curry (op +) o (fn Direct_Rec _ => 2 | _ => 1)) calls 0;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   178
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   179
      val no_calls' = tag_list 0 calls
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   180
        |> map_filter (try (apsnd (fn No_Rec n => n | Direct_Rec (n, _) => n)));
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   181
      val direct_calls' = tag_list 0 calls
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   182
        |> map_filter (try (apsnd (fn Direct_Rec (_, n) => n)));
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   183
      val indirect_calls' = tag_list 0 calls
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   184
        |> map_filter (try (apsnd (fn Indirect_Rec n => n)));
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   185
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   186
      fun make_direct_type T = dummyT; (* FIXME? *)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   187
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   188
      val rec_res_type_list = map (fn (x :: _) => (#rec_type x, #res_type x)) funs_data;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   189
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   190
      fun make_indirect_type (Type (Tname, Ts)) = Type (Tname, Ts |> map (fn T =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   191
        let val maybe_res_type = AList.lookup (op =) rec_res_type_list T in
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   192
          if is_some maybe_res_type
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   193
          then HOLogic.mk_prodT (T, the maybe_res_type)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   194
          else make_indirect_type T end))
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   195
        | make_indirect_type T = T;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   196
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   197
      val args = replicate n_args ("", dummyT)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   198
        |> Term.rename_wrt_term t
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   199
        |> map Free
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   200
        |> fold (fn (ctr_arg_idx, arg_idx) =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   201
            nth_map arg_idx (K (nth ctr_args ctr_arg_idx)))
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   202
          no_calls'
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   203
        |> fold (fn (ctr_arg_idx, arg_idx) =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   204
            nth_map arg_idx (K (nth ctr_args ctr_arg_idx |> map_types make_direct_type)))
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   205
          direct_calls'
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   206
        |> fold (fn (ctr_arg_idx, arg_idx) =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   207
            nth_map arg_idx (K (nth ctr_args ctr_arg_idx |> map_types make_indirect_type)))
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   208
          indirect_calls';
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   209
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   210
      val fun_name_ctr_pos_list =
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   211
        map (fn (x :: _) => (#fun_name x, length (#left_args x))) funs_data;
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   212
      val get_ctr_pos = try (the o AList.lookup (op =) fun_name_ctr_pos_list) #> the_default ~1;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   213
      val direct_calls = map (apfst (nth ctr_args) o apsnd (nth args)) direct_calls';
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   214
      val indirect_calls = map (apfst (nth ctr_args) o apsnd (nth args)) indirect_calls';
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   215
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   216
      val abstractions = args @ #left_args eqn_data @ #right_args eqn_data;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   217
    in
53350
17632ef6cfe8 simplified recursive calls' replacement
panny
parents: 53341
diff changeset
   218
      t
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   219
      |> subst_rec_calls lthy get_ctr_pos has_call ctr_args direct_calls indirect_calls
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   220
      |> fold_rev lambda abstractions
53350
17632ef6cfe8 simplified recursive calls' replacement
panny
parents: 53341
diff changeset
   221
    end;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   222
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   223
fun build_defs lthy bs mxs funs_data rec_specs has_call =
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   224
  let
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   225
    val n_funs = length funs_data;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   226
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   227
    val ctr_spec_eqn_data_list' =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   228
      (take n_funs rec_specs |> map #ctr_specs) ~~ funs_data
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   229
      |> maps (uncurry (finds (fn (x, y) => #ctr x = #ctr y))
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   230
          ##> (fn x => null x orelse
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   231
            primrec_error_eqns "excess equations in definition" (map #rhs_term x)) #> fst);
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   232
    val _ = ctr_spec_eqn_data_list' |> map (fn (_, x) => length x <= 1 orelse
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   233
      primrec_error_eqns ("multiple equations for constructor") (map #user_eqn x));
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   234
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   235
    val ctr_spec_eqn_data_list =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   236
      ctr_spec_eqn_data_list' @ (drop n_funs rec_specs |> maps #ctr_specs |> map (rpair []));
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   237
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   238
    val recs = take n_funs rec_specs |> map #recx;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   239
    val rec_args = ctr_spec_eqn_data_list
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   240
      |> sort ((op <) o pairself (#offset o fst) |> make_ord)
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   241
      |> map (uncurry (build_rec_arg lthy funs_data has_call) o apsnd (try the_single));
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   242
    val ctr_poss = map (fn x =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   243
      if length (distinct ((op =) o pairself (length o #left_args)) x) <> 1 then
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   244
        primrec_error ("inconstant constructor pattern position for function " ^
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   245
          quote (#fun_name (hd x)))
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   246
      else
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   247
        hd x |> #left_args |> length) funs_data;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   248
  in
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   249
    (recs, ctr_poss)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   250
    |-> map2 (fn recx => fn ctr_pos => list_comb (recx, rec_args) |> permute_args ctr_pos)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   251
    |> Syntax.check_terms lthy
53352
43a1cc050943 honor mixfix specifications
traytel
parents: 53341
diff changeset
   252
    |> map3 (fn b => fn mx => fn t => ((b, mx), ((Binding.map_name Thm.def_name b, []), t))) bs mxs
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   253
  end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   254
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   255
fun find_rec_calls has_call eqn_data =
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   256
  let
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   257
    fun find (Abs (_, _, b)) ctr_arg = find b ctr_arg
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   258
      | find (t as _ $ _) ctr_arg =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   259
        let
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   260
          val (f', args') = strip_comb t;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   261
          val n = find_index (equal ctr_arg) args';
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   262
        in
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   263
          if n < 0 then
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   264
            find f' ctr_arg @ maps (fn x => find x ctr_arg) args'
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   265
          else
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   266
            let val (f, args) = chop n args' |>> curry list_comb f' in
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   267
              if has_call f then
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   268
                f :: maps (fn x => find x ctr_arg) args
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   269
              else
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   270
                find f ctr_arg @ maps (fn x => find x ctr_arg) args
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   271
            end
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   272
        end
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   273
      | find _ _ = [];
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   274
  in
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   275
    map (find (#rhs_term eqn_data)) (#ctr_args eqn_data)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   276
    |> (fn [] => NONE | callss => SOME (#ctr eqn_data, callss))
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   277
  end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   278
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   279
fun add_primrec fixes specs lthy =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   280
  let
53352
43a1cc050943 honor mixfix specifications
traytel
parents: 53341
diff changeset
   281
    val (bs, mxs) = map_split (apfst fst) fixes;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   282
    val fun_names = map Binding.name_of bs;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   283
    val eqns_data = map (snd #> dissect_eqn lthy fun_names) specs;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   284
    val funs_data = eqns_data
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   285
      |> partition_eq ((op =) o pairself #fun_name)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   286
      |> finds (fn (x, y) => x = #fun_name (hd y)) fun_names |> fst
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   287
      |> map (fn (x, y) => the_single y handle List.Empty =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   288
          primrec_error ("missing equations for function " ^ quote x));
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   289
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   290
    val has_call = exists_subterm (map (fst #>> Binding.name_of #> Free) fixes |> member (op =));
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   291
    val arg_Ts = map (#rec_type o hd) funs_data;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   292
    val res_Ts = map (#res_type o hd) funs_data;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   293
    val callssss = funs_data
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   294
      |> map (partition_eq ((op =) o pairself #ctr))
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   295
      |> map (maps (map_filter (find_rec_calls has_call)));
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   296
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   297
    fun get_indices t = map (fst #>> Binding.name_of #> Free) fixes
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   298
      |> map_index (fn (i, v) => if exists_subterm (equal v) t then SOME i else NONE)
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   299
      |> map_filter I;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   300
    val ((nontriv, rec_specs, _, induct_thm, induct_thms), lthy') =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   301
      rec_specs_of bs arg_Ts res_Ts get_indices callssss lthy;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   302
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   303
    val actual_nn = length funs_data;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   304
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   305
    val _ = let val ctrs = (maps (map #ctr o #ctr_specs) rec_specs) in
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   306
      map (fn {ctr, user_eqn, ...} => member (op =) ctrs ctr orelse
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   307
        primrec_error_eqn ("argument " ^ quote (Syntax.string_of_term lthy' ctr) ^
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   308
          " is not a constructor in left-hand side") user_eqn) eqns_data end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   309
53358
b46e6cd75dc6 improved interfaces
panny
parents: 53357
diff changeset
   310
    val defs = build_defs lthy' bs mxs funs_data rec_specs has_call;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   311
53329
c31c0c311cf0 more canonical naming
blanchet
parents: 53310
diff changeset
   312
    fun prove def_thms' {ctr_specs, nested_map_idents, nested_map_comps, ...} induct_thm fun_data
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   313
        lthy =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   314
      let
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   315
        val fun_name = #fun_name (hd fun_data);
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   316
        val def_thms = map (snd o snd) def_thms';
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   317
        val simp_thms = finds (fn (x, y) => #ctr x = #ctr y) fun_data ctr_specs
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   318
          |> fst
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   319
          |> map_filter (try (fn (x, [y]) =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   320
            (#user_eqn x, length (#left_args x) + length (#right_args x), #rec_thm y)))
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   321
          |> map (fn (user_eqn, num_extra_args, rec_thm) =>
53329
c31c0c311cf0 more canonical naming
blanchet
parents: 53310
diff changeset
   322
            mk_primrec_tac lthy num_extra_args nested_map_idents nested_map_comps def_thms rec_thm
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   323
            |> K |> Goal.prove lthy [] [] user_eqn)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   324
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   325
        val notes =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   326
          [(inductN, if actual_nn > 1 then [induct_thm] else [], []),
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   327
           (simpsN, simp_thms, simp_attrs)]
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   328
          |> filter_out (null o #2)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   329
          |> map (fn (thmN, thms, attrs) =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   330
            ((Binding.qualify true fun_name (Binding.name thmN), attrs), [(thms, [])]));
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   331
      in
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   332
        lthy |> Local_Theory.notes notes
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   333
      end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   334
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   335
    val common_name = mk_common_name fun_names;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   336
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   337
    val common_notes =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   338
      [(inductN, if nontriv andalso actual_nn > 1 then [induct_thm] else [], [])]
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   339
      |> filter_out (null o #2)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   340
      |> map (fn (thmN, thms, attrs) =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   341
        ((Binding.qualify true common_name (Binding.name thmN), attrs), [(thms, [])]));
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   342
  in
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   343
    lthy'
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   344
    |> fold_map Local_Theory.define defs
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   345
    |-> (fn def_thms' => fold_map3 (prove def_thms') (take actual_nn rec_specs)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   346
      (take actual_nn induct_thms) funs_data)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   347
    |> snd
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   348
    |> Local_Theory.notes common_notes |> snd
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   349
  end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   350
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   351
fun add_primrec_cmd raw_fixes raw_specs lthy =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   352
  let
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   353
    val _ = let val d = duplicates (op =) (map (Binding.name_of o #1) raw_fixes) in null d orelse
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   354
      primrec_error ("duplicate function name(s): " ^ commas d) end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   355
    val (fixes, specs) = fst (Specification.read_spec raw_fixes raw_specs lthy);
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   356
  in
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   357
    add_primrec fixes specs lthy
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   358
      handle ERROR str => primrec_error str
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   359
  end
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   360
  handle Primrec_Error (str, eqns) =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   361
    if null eqns
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   362
    then error ("primrec_new error:\n  " ^ str)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   363
    else error ("primrec_new error:\n  " ^ str ^ "\nin\n  " ^
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   364
      space_implode "\n  " (map (quote o Syntax.string_of_term lthy) eqns))
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   365
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   366
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   367
53310
8af01463b2d3 moved keywords down the hierarchy
blanchet
parents: 53304
diff changeset
   368
(* Primcorec *)
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   369
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   370
type co_eqn_data_disc = {
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   371
  fun_name: string,
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   372
  fun_args: term list,
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   373
  ctr_no: int, (*###*)
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   374
  cond: term,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   375
  user_eqn: term
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   376
};
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   377
type co_eqn_data_sel = {
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   378
  fun_name: string,
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   379
  fun_args: term list,
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   380
  ctr: term,
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   381
  sel: term,
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   382
  rhs_term: term,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   383
  user_eqn: term
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   384
};
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   385
datatype co_eqn_data =
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   386
  Disc of co_eqn_data_disc |
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   387
  Sel of co_eqn_data_sel;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   388
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   389
fun co_dissect_eqn_disc sequential fun_name_corec_spec_list eqn' imp_lhs' imp_rhs matched_conds =
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   390
  let
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   391
    fun find_subterm p = let (* FIXME \<exists>? *)
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   392
      fun f (t as u $ v) = if p t then SOME t else merge_options (f u, f v)
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   393
        | f t = if p t then SOME t else NONE
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   394
      in f end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   395
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   396
    val fun_name = imp_rhs
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   397
      |> perhaps (try HOLogic.dest_not)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   398
      |> `(try (fst o dest_Free o head_of o snd o dest_comb))
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   399
      ||> (try (fst o dest_Free o head_of o fst o HOLogic.dest_eq))
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   400
      |> the o merge_options;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   401
    val corec_spec = the (AList.lookup (op =) fun_name_corec_spec_list fun_name)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   402
      handle Option.Option => primrec_error_eqn "malformed discriminator equation" imp_rhs;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   403
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   404
    val discs = #ctr_specs corec_spec |> map #disc;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   405
    val ctrs = #ctr_specs corec_spec |> map #ctr;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   406
    val not_disc = head_of imp_rhs = @{term Not};
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   407
    val _ = not_disc andalso length ctrs <> 2 andalso
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   408
      primrec_error_eqn "\<not>ed discriminator for a type with \<noteq> 2 constructors" imp_rhs;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   409
    val disc = find_subterm (member (op =) discs o head_of) imp_rhs;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   410
    val eq_ctr0 = imp_rhs |> perhaps (try (HOLogic.dest_not)) |> try (HOLogic.dest_eq #> snd)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   411
        |> (fn SOME t => let val n = find_index (equal t) ctrs in
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   412
          if n >= 0 then SOME n else NONE end | _ => NONE);
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   413
    val _ = is_some disc orelse is_some eq_ctr0 orelse
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   414
      primrec_error_eqn "no discriminator in equation" imp_rhs;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   415
    val ctr_no' =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   416
      if is_none disc then the eq_ctr0 else find_index (equal (head_of (the disc))) discs;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   417
    val ctr_no = if not_disc then 1 - ctr_no' else ctr_no';
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   418
    val fun_args = if is_none disc
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   419
      then imp_rhs |> perhaps (try HOLogic.dest_not) |> HOLogic.dest_eq |> fst |> strip_comb |> snd
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   420
      else the disc |> the_single o snd o strip_comb
53357
46b0c7a08af7 simplified rewriting of map arguments
panny
parents: 53354
diff changeset
   421
        |> (fn t => if free_name (head_of t) = SOME fun_name
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   422
          then snd (strip_comb t) else []);
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   423
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   424
    val mk_conjs = try (foldr1 HOLogic.mk_conj) #> the_default @{const True};
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   425
    val mk_disjs = try (foldr1 HOLogic.mk_disj) #> the_default @{const False};
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   426
    val catch_all = try (fst o dest_Free o the_single) imp_lhs' = SOME Name.uu_;
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   427
    val matched_cond = filter (equal fun_name o fst) matched_conds |> map snd |> mk_disjs;
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   428
    val imp_lhs = mk_conjs imp_lhs'
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   429
      |> incr_boundvars (length fun_args)
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   430
      |> subst_atomic (fun_args ~~ map Bound (length fun_args - 1 downto 0))
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   431
    val cond =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   432
      if catch_all then
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   433
        matched_cond |> HOLogic.mk_not
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   434
      else if sequential then
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   435
        HOLogic.mk_conj (HOLogic.mk_not matched_cond, imp_lhs)
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   436
      else
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   437
        imp_lhs;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   438
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   439
    val matched_conds' =
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   440
      (fun_name, if catch_all orelse not sequential then cond else imp_lhs) :: matched_conds;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   441
  in
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   442
    (Disc {
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   443
      fun_name = fun_name,
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   444
      fun_args = fun_args,
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   445
      ctr_no = ctr_no,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   446
      cond = cond,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   447
      user_eqn = eqn'
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   448
    }, matched_conds')
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   449
  end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   450
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   451
fun co_dissect_eqn_sel fun_name_corec_spec_list eqn' eqn =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   452
  let
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   453
    val (lhs, rhs) = HOLogic.dest_eq eqn
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   454
      handle TERM _ =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   455
        primrec_error_eqn "malformed function equation (expected \"lhs = rhs\")" eqn;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   456
    val sel = head_of lhs;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   457
    val (fun_name, fun_args) = dest_comb lhs |> snd |> strip_comb |> apfst (fst o dest_Free)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   458
      handle TERM _ =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   459
        primrec_error_eqn "malformed selector argument in left-hand side" eqn;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   460
    val corec_spec = the (AList.lookup (op =) fun_name_corec_spec_list fun_name)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   461
      handle Option.Option => primrec_error_eqn "malformed selector argument in left-hand side" eqn;
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   462
    val (ctr_spec, sel) = #ctr_specs corec_spec
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   463
      |> the o get_index (try (the o find_first (equal sel) o #sels))
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   464
      |>> nth (#ctr_specs corec_spec);
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   465
  in
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   466
    Sel {
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   467
      fun_name = fun_name,
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   468
      fun_args = fun_args,
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   469
      ctr = #ctr ctr_spec,
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   470
      sel = sel,
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   471
      rhs_term = rhs,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   472
      user_eqn = eqn'
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   473
    }
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   474
  end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   475
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   476
fun co_dissect_eqn_ctr sequential fun_name_corec_spec_list eqn' imp_lhs' imp_rhs matched_conds =
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   477
  let 
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   478
    val (lhs, rhs) = HOLogic.dest_eq imp_rhs;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   479
    val fun_name = head_of lhs |> fst o dest_Free;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   480
    val corec_spec = the (AList.lookup (op =) fun_name_corec_spec_list fun_name);
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   481
    val (ctr, ctr_args) = strip_comb rhs;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   482
    val ctr_spec = the (find_first (equal ctr o #ctr) (#ctr_specs corec_spec))
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   483
      handle Option.Option => primrec_error_eqn "not a constructor" ctr;
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   484
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   485
    val disc_imp_rhs = betapply (#disc ctr_spec, lhs);
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   486
    val (maybe_eqn_data_disc, matched_conds') = if length (#ctr_specs corec_spec) = 1
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   487
      then (NONE, matched_conds)
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   488
      else apfst SOME (co_dissect_eqn_disc
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   489
          sequential fun_name_corec_spec_list eqn' imp_lhs' disc_imp_rhs matched_conds);
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   490
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   491
    val sel_imp_rhss = (#sels ctr_spec ~~ ctr_args)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   492
      |> map (fn (sel, ctr_arg) => HOLogic.mk_eq (betapply (sel, lhs), ctr_arg));
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   493
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   494
val _ = tracing ("reduced\n    " ^ Syntax.string_of_term @{context} imp_rhs ^ "\nto\n    \<cdot> " ^
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   495
 (is_some maybe_eqn_data_disc ? K (Syntax.string_of_term @{context} disc_imp_rhs ^ "\n    \<cdot> ")) "" ^
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   496
 space_implode "\n    \<cdot> " (map (Syntax.string_of_term @{context}) sel_imp_rhss));
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   497
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   498
    val eqns_data_sel =
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   499
      map (co_dissect_eqn_sel fun_name_corec_spec_list eqn') sel_imp_rhss;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   500
  in
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   501
    (map_filter I [maybe_eqn_data_disc] @ eqns_data_sel, matched_conds')
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   502
  end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   503
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   504
fun co_dissect_eqn sequential fun_name_corec_spec_list eqn' matched_conds =
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   505
  let
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   506
    val eqn = subst_bounds (strip_qnt_vars @{const_name all} eqn' |> map Free |> rev,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   507
        strip_qnt_body @{const_name all} eqn')
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   508
        handle TERM _ => primrec_error_eqn "malformed function equation" eqn';
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   509
    val (imp_lhs', imp_rhs) = Logic.strip_horn eqn
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   510
      |> apfst (map HOLogic.dest_Trueprop) o apsnd HOLogic.dest_Trueprop;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   511
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   512
    val head = imp_rhs
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   513
      |> perhaps (try HOLogic.dest_not) |> perhaps (try (fst o HOLogic.dest_eq))
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   514
      |> head_of;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   515
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   516
    val maybe_rhs = imp_rhs |> perhaps (try (HOLogic.dest_not)) |> try (snd o HOLogic.dest_eq);
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   517
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   518
    val fun_names = map fst fun_name_corec_spec_list;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   519
    val discs = maps (#ctr_specs o snd) fun_name_corec_spec_list |> map #disc;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   520
    val sels = maps (#ctr_specs o snd) fun_name_corec_spec_list |> maps #sels;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   521
    val ctrs = maps (#ctr_specs o snd) fun_name_corec_spec_list |> map #ctr;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   522
  in
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   523
    if member (op =) discs head orelse
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   524
      is_some maybe_rhs andalso
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   525
        member (op =) (filter (null o binder_types o fastype_of) ctrs) (the maybe_rhs) then
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   526
      co_dissect_eqn_disc sequential fun_name_corec_spec_list eqn' imp_lhs' imp_rhs matched_conds
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   527
      |>> single
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   528
    else if member (op =) sels head then
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   529
      ([co_dissect_eqn_sel fun_name_corec_spec_list eqn' imp_rhs], matched_conds)
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   530
    else if is_Free head andalso member (op =) fun_names (fst (dest_Free head)) then
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   531
      co_dissect_eqn_ctr sequential fun_name_corec_spec_list eqn' imp_lhs' imp_rhs matched_conds
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   532
    else
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   533
      primrec_error_eqn "malformed function equation" eqn
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   534
  end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   535
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   536
fun build_corec_args_discs disc_eqns ctr_specs =
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   537
  if null disc_eqns then I else
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   538
    let
53411
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   539
(*val _ = tracing ("d/p:\<cdot> " ^ space_implode "\n    \<cdot> " (map ((op ^) o
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   540
 apfst (Syntax.string_of_term @{context}) o apsnd (curry (op ^) " / " o @{make_string}))
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   541
  (ctr_specs |> map_filter (fn {disc, pred = SOME pred, ...} => SOME (disc, pred) | _ => NONE))));*)
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   542
      val conds = map #cond disc_eqns;
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   543
      val fun_args = #fun_args (hd disc_eqns);
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   544
      val args =
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   545
        if length ctr_specs = 1 then []
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   546
        else if length disc_eqns = length ctr_specs then
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   547
          fst (split_last conds)
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   548
        else if length disc_eqns = length ctr_specs - 1 then
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   549
          let val n = 0 upto length ctr_specs - 1
53411
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   550
              |> the(*###*) o find_first (fn idx => not (exists (equal idx o #ctr_no) disc_eqns)) in
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   551
            if n = length ctr_specs - 1 then
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   552
              conds
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   553
            else
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   554
              split_last conds
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   555
              ||> HOLogic.mk_not
53411
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   556
              |> `(uncurry (fold (curry HOLogic.mk_conj o HOLogic.mk_not)))
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   557
              ||> chop n o fst
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   558
              |> (fn (x, (l, r)) => l @ (x :: r))
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   559
          end
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   560
        else
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   561
          0 upto length ctr_specs - 1
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   562
          |> map (fn idx => find_first (equal idx o #ctr_no) disc_eqns
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   563
            |> Option.map #cond
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   564
            |> the_default undef_const)
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   565
          |> fst o split_last;
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   566
    in
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   567
      (* FIXME deal with #preds above *)
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   568
      (map_filter #pred ctr_specs, args)
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   569
      |-> fold2 (fn idx => fn t => nth_map idx
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   570
        (K (subst_bounds (List.rev fun_args, t)
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   571
          |> HOLogic.tupled_lambda (HOLogic.mk_tuple fun_args))))
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   572
    end;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   573
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   574
fun build_corec_arg_no_call sel_eqns sel = find_first (equal sel o #sel) sel_eqns
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   575
  |> try (fn SOME sel_eqn => (#fun_args sel_eqn, #rhs_term sel_eqn))
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   576
  |> the_default ([], undef_const)
53411
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   577
  |-> abs_tuple
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   578
  |> K;
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   579
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   580
fun build_corec_arg_direct_call lthy has_call sel_eqns sel =
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   581
  let
53411
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   582
    val maybe_sel_eqn = find_first (equal sel o #sel) sel_eqns;
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   583
    fun rewrite is_end U T t =
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   584
      if U = @{typ bool} then @{term True} |> has_call t ? K @{term False} (* stop? *)
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   585
      else if is_end = has_call t then undef_const
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   586
      else if is_end then t (* end *)
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   587
      else HOLogic.mk_tuple (snd (strip_comb t)); (* continue *)
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   588
    fun massage rhs_term is_end t = massage_direct_corec_call
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   589
      lthy has_call (rewrite is_end) [] (range_type (fastype_of t)) rhs_term;
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   590
  in
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   591
    if is_none maybe_sel_eqn then K I else
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   592
      abs_tuple (#fun_args (the maybe_sel_eqn)) oo massage (#rhs_term (the maybe_sel_eqn))
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   593
  end;
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   594
53411
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   595
fun build_corec_arg_indirect_call lthy has_call sel_eqns sel =
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   596
  let
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   597
    val maybe_sel_eqn = find_first (equal sel o #sel) sel_eqns;
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   598
    fun rewrite _ _ =
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   599
      let
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   600
        fun subst (Abs (v, T, b)) = Abs (v, T, subst b)
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   601
          | subst (t as _ $ _) =
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   602
            let val (u, vs) = strip_comb t in
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   603
              if is_Free u andalso has_call u then
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   604
                Const (@{const_name Inr}, dummyT) $ (*HOLogic.mk_tuple vs*)
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   605
                  (try (foldr1 (fn (x, y) => Const (@{const_name Pair}, dummyT) $ x $ y)) vs
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   606
                    |> the_default (hd vs))
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   607
              else if try (fst o dest_Const) u = SOME @{const_name prod_case} then
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   608
                list_comb (u |> map_types (K dummyT), map subst vs)
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   609
              else
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   610
                list_comb (subst u, map subst vs)
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   611
            end
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   612
          | subst t = t;
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   613
      in
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   614
        subst
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   615
      end;
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   616
    fun massage rhs_term t = massage_indirect_corec_call
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   617
      lthy has_call rewrite [] (fastype_of t |> range_type) rhs_term;
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   618
  in
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   619
    if is_none maybe_sel_eqn then I else
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   620
      abs_tuple (#fun_args (the maybe_sel_eqn)) o massage (#rhs_term (the maybe_sel_eqn))
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   621
  end;
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   622
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   623
fun build_corec_args_sel lthy has_call all_sel_eqns ctr_spec =
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   624
  let val sel_eqns = filter (equal (#ctr ctr_spec) o #ctr) all_sel_eqns in
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   625
    if null sel_eqns then I else
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   626
      let
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   627
        val sel_call_list = #sels ctr_spec ~~ #calls ctr_spec;
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   628
53411
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   629
(*val _ = tracing ("s/c:\<cdot> " ^ space_implode "\n    \<cdot> " (map ((op ^) o
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   630
 apfst (Syntax.string_of_term lthy) o apsnd (curry (op ^) " / " o @{make_string}))
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   631
  sel_call_list));*)
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   632
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   633
        val no_calls' = map_filter (try (apsnd (fn No_Corec n => n))) sel_call_list;
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   634
        val direct_calls' = map_filter (try (apsnd (fn Direct_Corec n => n))) sel_call_list;
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   635
        val indirect_calls' = map_filter (try (apsnd (fn Indirect_Corec n => n))) sel_call_list;
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   636
      in
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   637
        I
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   638
        #> fold (fn (sel, n) => nth_map n
53411
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   639
          (build_corec_arg_no_call sel_eqns sel)) no_calls'
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   640
        #> fold (fn (sel, (q, g, h)) =>
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   641
          let val f = build_corec_arg_direct_call lthy has_call sel_eqns sel in
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   642
            nth_map h (f false) o nth_map g (f true) o nth_map q (f true) end) direct_calls'
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   643
        #> fold (fn (sel, n) => nth_map n
53411
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   644
          (build_corec_arg_indirect_call lthy has_call sel_eqns sel)) indirect_calls'
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   645
      end
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   646
  end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   647
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   648
fun co_build_defs lthy sequential bs mxs has_call arg_Tss fun_name_corec_spec_list eqns_data =
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   649
  let
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   650
    val fun_names = map Binding.name_of bs;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   651
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   652
    val disc_eqnss = map_filter (try (fn Disc x => x)) eqns_data
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   653
      |> partition_eq ((op =) o pairself #fun_name)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   654
      |> finds (fn (x, ({fun_name, ...} :: _)) => x = fun_name) fun_names |> fst
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   655
      |> map (sort ((op <) o pairself #ctr_no |> make_ord) o flat o snd);
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   656
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   657
    val _ = disc_eqnss |> map (fn x =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   658
      let val d = duplicates ((op =) o pairself #ctr_no) x in null d orelse
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   659
        primrec_error_eqns "excess discriminator equations in definition"
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   660
          (maps (fn t => filter (equal (#ctr_no t) o #ctr_no) x) d |> map #user_eqn) end);
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   661
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   662
(*val _ = tracing ("disc_eqnss:\n    \<cdot> " ^ space_implode "\n    \<cdot> " (map @{make_string} disc_eqnss));*)
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   663
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   664
    val sel_eqnss = map_filter (try (fn Sel x => x)) eqns_data
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   665
      |> partition_eq ((op =) o pairself #fun_name)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   666
      |> finds (fn (x, ({fun_name, ...} :: _)) => x = fun_name) fun_names |> fst
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   667
      |> map (flat o snd);
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   668
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   669
(*val _ = tracing ("sel_eqnss:\n    \<cdot> " ^ space_implode "\n    \<cdot> " (map @{make_string} sel_eqnss));*)
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   670
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   671
    val corecs = map (#corec o snd) fun_name_corec_spec_list;
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   672
    val ctr_specss = map (#ctr_specs o snd) fun_name_corec_spec_list;
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   673
    val corec_args = hd corecs
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   674
      |> fst o split_last o binder_types o fastype_of
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   675
      |> map (Const o pair @{const_name undefined})
53341
63015d035301 handle selector formulae with no corecursive calls
panny
parents: 53335
diff changeset
   676
      |> fold2 build_corec_args_discs disc_eqnss ctr_specss
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   677
      |> fold2 (fold o build_corec_args_sel lthy has_call) sel_eqnss ctr_specss;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   678
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   679
    fun currys Ts t = if length Ts <= 1 then t else
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   680
      t $ foldr1 (fn (u, v) => HOLogic.pair_const dummyT dummyT $ u $ v)
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   681
        (length Ts - 1 downto 0 |> map Bound)
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   682
      |> fold_rev (fn T => fn u => Abs (Name.uu, T, u)) Ts;
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   683
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   684
val _ = tracing ("corecursor arguments:\n    \<cdot> " ^
53411
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   685
 space_implode "\n    \<cdot> " (map (Syntax.string_of_term lthy) corec_args));
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   686
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   687
    fun uneq_pairs_rev xs = xs (* FIXME \<exists>? *)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   688
      |> these o try (split_last #> (fn (ys, y) => uneq_pairs_rev ys @ map (pair y) ys));
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   689
    val proof_obligations = if sequential then [] else
53411
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   690
      disc_eqnss
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   691
      |> maps (uneq_pairs_rev o map (fn {fun_args, cond, ...} => (fun_args, cond)))
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   692
      |> map (fn ((fun_args, x), (_, y)) => [x, HOLogic.mk_not y]
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   693
        |> map (HOLogic.mk_Trueprop o curry subst_bounds (List.rev fun_args))
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   694
        |> curry list_comb @{const ==>});
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   695
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   696
val _ = tracing ("proof obligations:\n    \<cdot> " ^
53411
ab4edf89992f support indirect corecursion
panny
parents: 53401
diff changeset
   697
 space_implode "\n    \<cdot> " (map (Syntax.string_of_term lthy) proof_obligations));
53401
2101a97e6220 various refactoring;
panny
parents: 53360
diff changeset
   698
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   699
  in
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   700
    map (list_comb o rpair corec_args) corecs
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   701
    |> map2 (fn Ts => fn t => if length Ts = 0 then t $ HOLogic.unit else t) arg_Tss
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   702
    |> map2 currys arg_Tss
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   703
    |> Syntax.check_terms lthy
53352
43a1cc050943 honor mixfix specifications
traytel
parents: 53341
diff changeset
   704
    |> map3 (fn b => fn mx => fn t => ((b, mx), ((Binding.map_name Thm.def_name b, []), t))) bs mxs
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   705
    |> rpair proof_obligations
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   706
  end;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   707
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   708
fun add_primcorec sequential fixes specs lthy =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   709
  let
53352
43a1cc050943 honor mixfix specifications
traytel
parents: 53341
diff changeset
   710
    val (bs, mxs) = map_split (apfst fst) fixes;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   711
    val (arg_Ts, res_Ts) = map (strip_type o snd o fst #>> HOLogic.mk_tupleT) fixes |> split_list;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   712
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   713
    (* copied from primrec_new *)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   714
    fun get_indices t = map (fst #>> Binding.name_of #> Free) fixes
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   715
      |> map_index (fn (i, v) => if exists_subterm (equal v) t then SOME i else NONE)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   716
      |> map_filter I;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   717
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   718
    val callssss = []; (* FIXME *)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   719
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   720
    val ((nontriv, corec_specs, _, coinduct_thm, strong_co_induct_thm, coinduct_thmss,
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   721
          strong_coinduct_thmss), lthy') =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   722
      corec_specs_of bs arg_Ts res_Ts get_indices callssss lthy;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   723
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   724
    val fun_names = map Binding.name_of bs;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   725
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   726
    val fun_name_corec_spec_list = (fun_names ~~ res_Ts, corec_specs)
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   727
      |> uncurry (finds (fn ((_, T), {corec, ...}) => T = body_type (fastype_of corec))) |> fst
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   728
      |> map (apfst fst #> apsnd the_single); (*###*)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   729
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   730
    val (eqns_data, _) =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   731
      fold_map (co_dissect_eqn sequential fun_name_corec_spec_list) (map snd specs) []
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   732
      |>> flat;
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   733
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   734
    val has_call = exists_subterm (map (fst #>> Binding.name_of #> Free) fixes |> member (op =));
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   735
    val arg_Tss = map (binder_types o snd o fst) fixes;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   736
    val (defs, proof_obligations) =
53360
7ffc4a746a73 handle direct corecursion
panny
parents: 53358
diff changeset
   737
      co_build_defs lthy' sequential bs mxs has_call arg_Tss fun_name_corec_spec_list eqns_data;
53303
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   738
  in
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   739
    lthy'
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   740
    |> fold_map Local_Theory.define defs |> snd
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   741
    |> Proof.theorem NONE (K I) [map (rpair []) proof_obligations]
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   742
    |> Proof.refine (Method.primitive_text I)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   743
    |> Seq.hd
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   744
  end
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   745
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   746
fun add_primcorec_cmd seq (raw_fixes, raw_specs) lthy =
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   747
  let
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   748
    val (fixes, specs) = fst (Specification.read_spec raw_fixes raw_specs lthy);
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   749
  in
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   750
    add_primcorec seq fixes specs lthy
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   751
    handle ERROR str => primrec_error str
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   752
  end
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   753
  handle Primrec_Error (str, eqns) =>
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   754
    if null eqns
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   755
    then error ("primcorec error:\n  " ^ str)
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   756
    else error ("primcorec error:\n  " ^ str ^ "\nin\n  " ^
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   757
      space_implode "\n  " (map (quote o Syntax.string_of_term lthy) eqns))
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   758
ae49b835ca01 moved files related to "primrec_new", "primcorec", and "datatype_compat" from bitbucket co-rec repository
blanchet
parents:
diff changeset
   759
end;