src/Provers/splitter.ML
author nipkow
Thu Apr 13 10:20:55 1995 +0200 (1995-04-13)
changeset 1030 1d8fa2fc4b9c
parent 943 8477483f663f
child 1064 5d6fb2c938e0
permissions -rw-r--r--
Completely rewrote split_tac. The old one failed in strange circumstances.
nipkow@4
     1
(*  Title:      Provers/splitter
nipkow@4
     2
    ID:         $Id$
nipkow@4
     3
    Author:     Tobias Nipkow
nipkow@1030
     4
    Copyright   1995  TU Munich
nipkow@4
     5
nipkow@4
     6
Generic case-splitter, suitable for most logics.
nipkow@4
     7
clasohm@0
     8
Use:
clasohm@0
     9
clasohm@0
    10
val split_tac = mk_case_split_tac iffD;
clasohm@0
    11
clasohm@0
    12
by(case_split_tac splits i);
clasohm@0
    13
clasohm@0
    14
where splits = [P(elim(...)) == rhs, ...]
clasohm@0
    15
      iffD  = [| P <-> Q; Q |] ==> P (* is called iffD2 in HOL *)
clasohm@0
    16
clasohm@0
    17
*)
clasohm@0
    18
clasohm@0
    19
fun mk_case_split_tac iffD =
clasohm@0
    20
let
clasohm@0
    21
nipkow@943
    22
val lift =
nipkow@943
    23
  let val ct = read_cterm (#sign(rep_thm iffD))
nipkow@943
    24
           ("[| !!x::'b::logic. Q(x) == R(x) |] ==> \
nipkow@943
    25
            \P(%x.Q(x)) == P(%x.R(x))::'a::logic",propT)
nipkow@943
    26
  in prove_goalw_cterm [] ct
nipkow@943
    27
     (fn [prem] => [rewtac prem, rtac reflexive_thm 1])
nipkow@943
    28
  end;
nipkow@4
    29
clasohm@0
    30
val trlift = lift RS transitive_thm;
clasohm@0
    31
val _ $ (Var(P,PT)$_) $ _ = concl_of trlift;
clasohm@0
    32
clasohm@0
    33
nipkow@1030
    34
fun mk_cntxt Ts t pos T maxi =
nipkow@1030
    35
  let fun var (t,i) = Var(("X",i),type_of1(Ts,t));
nipkow@1030
    36
      fun down [] t i = Bound 0
nipkow@1030
    37
        | down (p::ps) t i =
nipkow@1030
    38
            let val (h,ts) = strip_comb t
nipkow@1030
    39
                val v1 = map var (take(p,ts) ~~ (i upto (i+p-1)))
nipkow@1030
    40
                val u::us = drop(p,ts)
nipkow@1030
    41
                val v2 = map var (us ~~ ((i+p) upto (i+length(ts)-2)))
nipkow@1030
    42
      in list_comb(h,v1@[down ps u (i+length ts)]@v2) end;
nipkow@1030
    43
  in Abs("", T, down (rev pos) t maxi) end;
nipkow@1030
    44
nipkow@1030
    45
fun add_lbnos(is,t) = add_loose_bnos(t,0,is);
nipkow@1030
    46
nipkow@1030
    47
fun typ_test _ [] = true
nipkow@1030
    48
  | typ_test T ((_,U,_)::_) = (T=U);
clasohm@0
    49
nipkow@1030
    50
fun mk_split_pack(thm,T,n,ts,apsns) =
nipkow@1030
    51
  if n <= length ts andalso typ_test T apsns
nipkow@1030
    52
  then let val lev = length apsns
nipkow@1030
    53
           val lbnos = foldl add_lbnos ([],take(n,ts))
nipkow@1030
    54
           val flbnos = filter (fn i => i < lev) lbnos
nipkow@1030
    55
       in [(thm, if null flbnos then [] else rev apsns)] end
nipkow@1030
    56
  else [];
clasohm@0
    57
nipkow@1030
    58
fun split_posns cmap Ts t =
nipkow@1030
    59
  let fun posns Ts pos apsns (Abs(_,T,t)) =
nipkow@1030
    60
            let val U = fastype_of1(T::Ts,t)
nipkow@1030
    61
            in posns (T::Ts) (0::pos) ((T,U,pos)::apsns) t end
nipkow@1030
    62
        | posns Ts pos apsns t =
nipkow@1030
    63
            let val (h,ts) = strip_comb t
nipkow@1030
    64
                fun iter((i,a),t) = (i+1, (posns Ts (i::pos) apsns t) @ a);
nipkow@1030
    65
                val a = case h of
nipkow@1030
    66
                  Const(c,_) =>
nipkow@1030
    67
                    (case assoc(cmap,c) of
nipkow@1030
    68
                       Some(thm,T,n) => mk_split_pack(thm,T,n,ts,apsns)
nipkow@1030
    69
                     | None => [])
nipkow@1030
    70
                | _ => []
nipkow@1030
    71
             in snd(foldl iter ((0,a),ts)) end
nipkow@1030
    72
  in posns Ts [] [] t end;
clasohm@0
    73
clasohm@0
    74
fun nth_subgoal i thm = nth_elem(i-1,prems_of thm);
clasohm@0
    75
nipkow@1030
    76
fun shorter((_,ps),(_,qs)) = length ps <= length qs;
clasohm@0
    77
nipkow@1030
    78
fun select cmap state i =
nipkow@1030
    79
  let val goali = nth_subgoal i state
nipkow@1030
    80
      val Ts = rev(map #2 (Logic.strip_params goali))
nipkow@1030
    81
      val _ $ t $ _ = Logic.strip_assums_concl goali;
nipkow@1030
    82
  in (Ts,t,sort shorter (split_posns cmap Ts t)) end;
nipkow@1030
    83
nipkow@1030
    84
fun inst_lift Ts t (T,U,pos) state lift i =
clasohm@0
    85
  let val sg = #sign(rep_thm state)
clasohm@0
    86
      val tsig = #tsig(Sign.rep_sg sg)
nipkow@1030
    87
      val cntxt = mk_cntxt Ts t pos (T-->U) (#maxidx(rep_thm lift))
lcp@231
    88
      val cu = cterm_of sg cntxt
lcp@231
    89
      val uT = #T(rep_cterm cu)
lcp@231
    90
      val cP' = cterm_of sg (Var(P,uT))
clasohm@0
    91
      val ixnTs = Type.typ_match tsig ([],(PT,uT));
lcp@231
    92
      val ixncTs = map (fn (x,y) => (x,ctyp_of sg y)) ixnTs;
clasohm@0
    93
  in instantiate (ixncTs, [(cP',cu)]) lift end;
clasohm@0
    94
clasohm@0
    95
clasohm@0
    96
fun split_tac [] i = no_tac
clasohm@0
    97
  | split_tac splits i =
nipkow@1030
    98
  let fun const(thm) = let val _$(t as _$lhs)$_ = concl_of thm
clasohm@0
    99
                           val (Const(a,_),args) = strip_comb lhs
nipkow@1030
   100
                       in (a,(thm,fastype_of t,length args)) end
clasohm@0
   101
      val cmap = map const splits;
nipkow@1030
   102
      fun lift Ts t p state = rtac (inst_lift Ts t p state trlift i) i
nipkow@1030
   103
      fun lift_split state =
nipkow@1030
   104
            let val (Ts,t,splits) = select cmap state i
nipkow@1030
   105
            in case splits of
nipkow@1030
   106
                 [] => no_tac
nipkow@1030
   107
               | (thm,apsns)::_ =>
nipkow@1030
   108
                   (case apsns of
nipkow@1030
   109
                      [] => rtac thm i
nipkow@1030
   110
                    | p::_ => EVERY[STATE(lift Ts t p),
nipkow@1030
   111
                                    rtac reflexive_thm (i+1),
nipkow@1030
   112
                                    STATE lift_split])
nipkow@1030
   113
            end
clasohm@0
   114
  in STATE(fn thm =>
nipkow@1030
   115
       if i <= nprems_of thm then rtac iffD i THEN STATE lift_split
clasohm@0
   116
       else no_tac)
clasohm@0
   117
  end;
clasohm@0
   118
clasohm@0
   119
in split_tac end;