src/Provers/IsaPlanner/isand.ML
changeset 19835 81d6dc597559
child 19861 620d90091788
equal deleted inserted replaced
19834:2290cc06049b 19835:81d6dc597559
       
     1 (* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *) 
       
     2 (*  Title:      Pure/IsaPlanner/isand.ML
       
     3     ID:		$Id$
       
     4     Author:     Lucas Dixon, University of Edinburgh
       
     5                 lucas.dixon@ed.ac.uk
       
     6     Updated:    26 Apr 2005
       
     7     Date:       6 Aug 2004
       
     8 *)
       
     9 (* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- *) 
       
    10 (*  DESCRIPTION:
       
    11 
       
    12     Natural Deduction tools
       
    13 
       
    14     For working with Isabelle theorems in a natural detuction style.
       
    15     ie, not having to deal with meta level quantified varaibles,
       
    16     instead, we work with newly introduced frees, and hide the
       
    17     "all"'s, exporting results from theorems proved with the frees, to
       
    18     solve the all cases of the previous goal. This allows resolution
       
    19     to do proof search normally. 
       
    20 
       
    21     Note: A nice idea: allow exporting to solve any subgoal, thus
       
    22     allowing the interleaving of proof, or provide a structure for the
       
    23     ordering of proof, thus allowing proof attempts in parrell, but
       
    24     recording the order to apply things in.
       
    25 
       
    26     debugging tools:
       
    27 
       
    28     fun asm_mk t = (assume (cterm_of (Theory.sign_of (the_context())) t)); 
       
    29     fun asm_read s =  
       
    30       (assume (read_cterm (Theory.sign_of (Context.the_context())) (s,propT)));
       
    31 
       
    32     THINK: are we really ok with our varify name w.r.t the prop - do
       
    33     we also need to avoid names in the hidden hyps? What about
       
    34     unification contraints in flex-flex pairs - might they also have
       
    35     extra free vars?
       
    36 *)
       
    37 
       
    38 signature ISA_ND =
       
    39 sig
       
    40 
       
    41   (* export data *)
       
    42   datatype export = export of
       
    43            {gth: Thm.thm, (* initial goal theorem *)
       
    44             sgid: int, (* subgoal id which has been fixed etc *)
       
    45             fixes: Thm.cterm list, (* frees *)
       
    46             assumes: Thm.cterm list} (* assumptions *)
       
    47   val fixes_of_exp : export -> Thm.cterm list
       
    48   val export_back : export -> Thm.thm -> Thm.thm Seq.seq
       
    49   val export_solution : export -> Thm.thm -> Thm.thm
       
    50   val export_solutions : export list * Thm.thm -> Thm.thm
       
    51 
       
    52   (* inserting meta level params for frees in the conditions *)
       
    53   val allify_conditions :
       
    54       (Term.term -> Thm.cterm) ->
       
    55       (string * Term.typ) list -> Thm.thm -> Thm.thm * Thm.cterm list
       
    56   val allify_conditions' :
       
    57       (string * Term.typ) list -> Thm.thm -> Thm.thm * Thm.cterm list
       
    58   val assume_allified :
       
    59       theory -> (string * Term.sort) list * (string * Term.typ) list
       
    60       -> Term.term -> (Thm.cterm * Thm.thm)
       
    61 
       
    62   (* meta level fixed params (i.e. !! vars) *)
       
    63   val fix_alls_in_term : Term.term -> Term.term * Term.term list
       
    64   val fix_alls_term : int -> Term.term -> Term.term * Term.term list
       
    65   val fix_alls_cterm : int -> Thm.thm -> Thm.cterm * Thm.cterm list
       
    66   val fix_alls' : int -> Thm.thm -> Thm.thm * Thm.cterm list
       
    67   val fix_alls : int -> Thm.thm -> Thm.thm * export
       
    68 
       
    69   (* meta variables in types and terms *)
       
    70   val fix_tvars_to_tfrees_in_terms 
       
    71       : string list (* avoid these names *)
       
    72         -> Term.term list -> 
       
    73         (((string * int) * Term.sort) * (string * Term.sort)) list (* renamings *)
       
    74   val fix_vars_to_frees_in_terms
       
    75       : string list (* avoid these names *)
       
    76         -> Term.term list ->
       
    77         (((string * int) * Term.typ) * (string * Term.typ)) list (* renamings *)
       
    78   val fix_tvars_to_tfrees : Thm.thm -> Thm.ctyp list * Thm.thm
       
    79   val fix_vars_to_frees : Thm.thm -> Thm.cterm list * Thm.thm
       
    80   val fix_vars_and_tvars : 
       
    81       Thm.thm -> (Thm.cterm list * Thm.ctyp list) * Thm.thm
       
    82   val fix_vars_upto_idx : int -> Thm.thm -> Thm.thm
       
    83   val fix_tvars_upto_idx : int -> Thm.thm -> Thm.thm
       
    84   val unfix_frees : Thm.cterm list -> Thm.thm -> Thm.thm
       
    85   val unfix_tfrees : Thm.ctyp list -> Thm.thm -> Thm.thm
       
    86   val unfix_frees_and_tfrees :
       
    87       (Thm.cterm list * Thm.ctyp list) -> Thm.thm -> Thm.thm
       
    88 
       
    89   (* assumptions/subgoals *)
       
    90   val assume_prems :
       
    91       int -> Thm.thm -> Thm.thm list * Thm.thm * Thm.cterm list
       
    92   val fixed_subgoal_thms : Thm.thm -> Thm.thm list * (Thm.thm list -> Thm.thm)
       
    93   val fixes_and_assumes : int -> Thm.thm -> Thm.thm list * Thm.thm * export
       
    94   val hide_other_goals : Thm.thm -> Thm.thm * Thm.cterm list
       
    95   val hide_prems : Thm.thm -> Thm.thm * Thm.cterm list
       
    96 
       
    97   (* abstracts cterms (vars) to locally meta-all bounds *)
       
    98   val prepare_goal_export : string list * Thm.cterm list -> Thm.thm 
       
    99                             -> int * Thm.thm
       
   100   val solve_with : Thm.thm -> Thm.thm -> Thm.thm Seq.seq
       
   101   val subgoal_thms : Thm.thm -> Thm.thm list * (Thm.thm list -> Thm.thm)
       
   102 end
       
   103 
       
   104 
       
   105 structure IsaND 
       
   106 : ISA_ND
       
   107 = struct
       
   108 
       
   109 (* Solve *some* subgoal of "th" directly by "sol" *)
       
   110 (* Note: this is probably what Markus ment to do upon export of a
       
   111 "show" but maybe he used RS/rtac instead, which would wrongly lead to
       
   112 failing if there are premices to the shown goal. 
       
   113 
       
   114 given: 
       
   115 sol : Thm.thm = [| Ai... |] ==> Ci
       
   116 th : Thm.thm = 
       
   117   [| ... [| Ai... |] ==> Ci ... |] ==> G
       
   118 results in: 
       
   119   [| ... [| Ai-1... |] ==> Ci-1
       
   120     [| Ai+1... |] ==> Ci+1 ...
       
   121   |] ==> G
       
   122 i.e. solves some subgoal of th that is identical to sol. 
       
   123 *)
       
   124 fun solve_with sol th = 
       
   125     let fun solvei 0 = Seq.empty
       
   126           | solvei i = 
       
   127             Seq.append (bicompose false (false,sol,0) i th, 
       
   128                         solvei (i - 1))
       
   129     in
       
   130       solvei (Thm.nprems_of th)
       
   131     end;
       
   132 
       
   133 
       
   134 (* Given ctertmify function, (string,type) pairs capturing the free
       
   135 vars that need to be allified in the assumption, and a theorem with
       
   136 assumptions possibly containing the free vars, then we give back the
       
   137 assumptions allified as hidden hyps. 
       
   138 
       
   139 Given: x 
       
   140 th: A vs ==> B vs 
       
   141 Results in: "B vs" [!!x. A x]
       
   142 *)
       
   143 fun allify_conditions ctermify Ts th = 
       
   144     let 
       
   145       val premts = Thm.prems_of th;
       
   146     
       
   147       fun allify_prem_var (vt as (n,ty),t)  = 
       
   148           (Term.all ty) $ (Abs(n,ty,Term.abstract_over (Free vt, t)))
       
   149 
       
   150       fun allify_prem Ts p = foldr allify_prem_var p Ts
       
   151 
       
   152       val cTs = map (ctermify o Free) Ts
       
   153       val cterm_asms = map (ctermify o allify_prem Ts) premts
       
   154       val allifyied_asm_thms = map (Drule.forall_elim_list cTs o Thm.assume) cterm_asms
       
   155     in 
       
   156       (Library.foldl (fn (x,y) => y COMP x) (th, allifyied_asm_thms), cterm_asms)
       
   157     end;
       
   158 
       
   159 fun allify_conditions' Ts th = 
       
   160     allify_conditions (Thm.cterm_of (Thm.sign_of_thm th)) Ts th;
       
   161 
       
   162 (* allify types *)
       
   163 fun allify_typ ts ty = 
       
   164     let 
       
   165       fun trec (x as (TFree (s,srt))) = 
       
   166           (case Library.find_first (fn (s2,srt2) => s = s2) ts
       
   167             of NONE => x
       
   168              | SOME (s2,_) => TVar ((s,0),srt))
       
   169             (*  Maybe add in check here for bad sorts? 
       
   170              if srt = srt2 then TVar ((s,0),srt) 
       
   171                else raise  ("thaw_typ", ts, ty) *)
       
   172           | trec (Type (s,typs)) = Type (s, map trec typs)
       
   173           | trec (v as TVar _) = v;
       
   174     in trec ty end;
       
   175 
       
   176 (* implicit types and term *)
       
   177 fun allify_term_typs ty = Term.map_term_types (allify_typ ty);
       
   178 
       
   179 (* allified version of term, given frees to allify over. Note that we
       
   180 only allify over the types on the given allified cterm, we can't do
       
   181 this for the theorem as we are not allowed type-vars in the hyp. *)
       
   182 (* FIXME: make the allified term keep the same conclusion as it
       
   183 started with, rather than a strictly more general version (ie use
       
   184 instantiate with initial params we abstracted from, rather than
       
   185 forall_elim_vars. *)
       
   186 fun assume_allified sgn (tyvs,vs) t = 
       
   187     let
       
   188       fun allify_var (vt as (n,ty),t)  = 
       
   189           (Term.all ty) $ (Abs(n,ty,Term.abstract_over (Free vt, t)))
       
   190       fun allify Ts p = List.foldr allify_var p Ts
       
   191 
       
   192       val ctermify = Thm.cterm_of sgn;
       
   193       val cvars = map (fn (n,ty) => ctermify (Var ((n,0),ty))) vs
       
   194       val allified_term = t |> allify vs;
       
   195       val ct = ctermify allified_term;
       
   196       val typ_allified_ct = ctermify (allify_term_typs tyvs allified_term);
       
   197     in (typ_allified_ct, 
       
   198         Drule.forall_elim_vars 0 (Thm.assume ct)) end;
       
   199 
       
   200 
       
   201 (* change type-vars to fresh type frees *)
       
   202 fun fix_tvars_to_tfrees_in_terms names ts = 
       
   203     let 
       
   204       val tfree_names = map fst (List.foldr Term.add_term_tfrees [] ts);
       
   205       val tvars = List.foldr Term.add_term_tvars [] ts;
       
   206       val (names',renamings) = 
       
   207           List.foldr (fn (tv as ((n,i),s),(Ns,Rs)) => 
       
   208                          let val n2 = Term.variant Ns n in 
       
   209                            (n2::Ns, (tv, (n2,s))::Rs)
       
   210                          end) (tfree_names @ names,[]) tvars;
       
   211     in renamings end;
       
   212 fun fix_tvars_to_tfrees th = 
       
   213     let 
       
   214       val sign = Thm.sign_of_thm th;
       
   215       val ctypify = Thm.ctyp_of sign;
       
   216       val tpairs = Thm.terms_of_tpairs (Thm.tpairs_of th);
       
   217       val renamings = fix_tvars_to_tfrees_in_terms 
       
   218                         [] ((Thm.prop_of th) :: tpairs);
       
   219       val crenamings = 
       
   220           map (fn (v,f) => (ctypify (TVar v), ctypify (TFree f)))
       
   221               renamings;
       
   222       val fixedfrees = map snd crenamings;
       
   223     in (fixedfrees, Thm.instantiate (crenamings, []) th) end;
       
   224 
       
   225 
       
   226 (* change type-free's to type-vars in th, skipping the ones in "ns" *)
       
   227 fun unfix_tfrees ns th = 
       
   228     let 
       
   229       val varfiytfrees = map (Term.dest_TFree o Thm.typ_of) ns
       
   230       val skiptfrees = subtract (op =) varfiytfrees (Term.add_term_tfrees (Thm.prop_of th,[]));
       
   231     in #2 (Thm.varifyT' skiptfrees th) end;
       
   232 
       
   233 (* change schematic/meta vars to fresh free vars, avoiding name clashes 
       
   234    with "names" *)
       
   235 fun fix_vars_to_frees_in_terms names ts = 
       
   236     let 
       
   237       val vars = map Term.dest_Var (List.foldr Term.add_term_vars [] ts);
       
   238       val Ns = List.foldr Term.add_term_names names ts;
       
   239       val (_,renamings) = 
       
   240           Library.foldl (fn ((Ns,Rs),v as ((n,i),ty)) => 
       
   241                     let val n2 = Term.variant Ns n in
       
   242                       (n2 :: Ns, (v, (n2,ty)) :: Rs)
       
   243                     end) ((Ns,[]), vars);
       
   244     in renamings end;
       
   245 fun fix_vars_to_frees th = 
       
   246     let 
       
   247       val ctermify = Thm.cterm_of (Thm.sign_of_thm th)
       
   248       val tpairs = Thm.terms_of_tpairs (Thm.tpairs_of th);
       
   249       val renamings = fix_vars_to_frees_in_terms 
       
   250                         [] ([Thm.prop_of th] @ tpairs);
       
   251       val crenamings = 
       
   252           map (fn (v,f) => (ctermify (Var v), ctermify (Free f)))
       
   253               renamings;
       
   254       val fixedfrees = map snd crenamings;
       
   255     in (fixedfrees, Thm.instantiate ([], crenamings) th) end;
       
   256 
       
   257 fun fix_tvars_upto_idx ix th = 
       
   258     let 
       
   259       val sgn = Thm.sign_of_thm th;
       
   260       val ctypify = Thm.ctyp_of sgn
       
   261       val tpairs = Thm.terms_of_tpairs (Thm.tpairs_of th);
       
   262       val prop = (Thm.prop_of th);
       
   263       val tvars = List.foldr Term.add_term_tvars [] (prop :: tpairs);
       
   264       val ctyfixes = 
       
   265           map_filter 
       
   266             (fn (v as ((s,i),ty)) => 
       
   267                 if i <= ix then SOME (ctypify (TVar v), ctypify (TFree (s,ty)))
       
   268                 else NONE) tvars;
       
   269     in Thm.instantiate (ctyfixes, []) th end;
       
   270 fun fix_vars_upto_idx ix th = 
       
   271     let 
       
   272       val sgn = Thm.sign_of_thm th;
       
   273       val ctermify = Thm.cterm_of sgn
       
   274       val tpairs = Thm.terms_of_tpairs (Thm.tpairs_of th);
       
   275       val prop = (Thm.prop_of th);
       
   276       val vars = map Term.dest_Var (List.foldr Term.add_term_vars 
       
   277                                                [] (prop :: tpairs));
       
   278       val cfixes = 
       
   279           map_filter 
       
   280             (fn (v as ((s,i),ty)) => 
       
   281                 if i <= ix then SOME (ctermify (Var v), ctermify (Free (s,ty)))
       
   282                 else NONE) vars;
       
   283     in Thm.instantiate ([], cfixes) th end;
       
   284 
       
   285 
       
   286 (* make free vars into schematic vars with index zero *)
       
   287  fun unfix_frees frees = 
       
   288      apply (map (K (Drule.forall_elim_var 0)) frees) 
       
   289      o Drule.forall_intr_list frees;
       
   290 
       
   291 (* fix term and type variables *)
       
   292 fun fix_vars_and_tvars th = 
       
   293     let val (tvars, th') = fix_tvars_to_tfrees th
       
   294       val (vars, th'') = fix_vars_to_frees th' 
       
   295     in ((vars, tvars), th'') end;
       
   296 
       
   297 (* implicit Thm.thm argument *)
       
   298 (* assumes: vars may contain fixed versions of the frees *)
       
   299 (* THINK: what if vs already has types varified? *)
       
   300 fun unfix_frees_and_tfrees (vs,tvs) = 
       
   301     (unfix_tfrees tvs o unfix_frees vs);
       
   302 
       
   303 (* datatype to capture an exported result, ie a fix or assume. *)
       
   304 datatype export = 
       
   305          export of {fixes : Thm.cterm list, (* fixed vars *)
       
   306                     assumes : Thm.cterm list, (* hidden hyps/assumed prems *)
       
   307                     sgid : int,
       
   308                     gth :  Thm.thm}; (* subgoal/goalthm *)
       
   309 
       
   310 fun fixes_of_exp (export rep) = #fixes rep;
       
   311 
       
   312 (* export the result of the new goal thm, ie if we reduced teh
       
   313 subgoal, then we get a new reduced subtgoal with the old
       
   314 all-quantified variables *)
       
   315 local 
       
   316 
       
   317 (* allify puts in a meta level univ quantifier for a free variavble *)
       
   318 fun allify_term (v, t) = 
       
   319     let val vt = #t (Thm.rep_cterm v)
       
   320       val (n,ty) = Term.dest_Free vt
       
   321     in (Term.all ty) $ (Abs(n,ty,Term.abstract_over (vt, t))) end;
       
   322 
       
   323 fun allify_for_sg_term ctermify vs t =
       
   324     let val t_alls = foldr allify_term t vs;
       
   325         val ct_alls = ctermify t_alls; 
       
   326     in 
       
   327       (ct_alls, Drule.forall_elim_list vs (Thm.assume ct_alls))
       
   328     end;
       
   329 (* lookup type of a free var name from a list *)
       
   330 fun lookupfree vs vn  = 
       
   331     case Library.find_first (fn (n,ty) => n = vn) vs of 
       
   332       NONE => error ("prepare_goal_export:lookupfree: " ^ vn ^ " does not occur in the term")
       
   333     | SOME x => x;
       
   334 in
       
   335 fun export_back (export {fixes = vs, assumes = hprems, 
       
   336                          sgid = i, gth = gth}) newth = 
       
   337     let 
       
   338       val sgn = Thm.sign_of_thm newth;
       
   339       val ctermify = Thm.cterm_of sgn;
       
   340 
       
   341       val sgs = prems_of newth;
       
   342       val (sgallcts, sgthms) = 
       
   343           Library.split_list (map (allify_for_sg_term ctermify vs) sgs);
       
   344       val minimal_newth = 
       
   345           (Library.foldl (fn ( newth', sgthm) => 
       
   346                           Drule.compose_single (sgthm, 1, newth'))
       
   347                       (newth, sgthms));
       
   348       val allified_newth = 
       
   349           minimal_newth 
       
   350             |> Drule.implies_intr_list hprems
       
   351             |> Drule.forall_intr_list vs 
       
   352 
       
   353       val newth' = Drule.implies_intr_list sgallcts allified_newth
       
   354     in
       
   355       bicompose false (false, newth', (length sgallcts)) i gth
       
   356     end;
       
   357 
       
   358 (* 
       
   359 Given "vs" : names of free variables to abstract over,
       
   360 Given cterms : premices to abstract over (P1... Pn) in terms of vs,
       
   361 Given a thm of the form: 
       
   362 P1 vs; ...; Pn vs ==> Goal(C vs)
       
   363 
       
   364 Gives back: 
       
   365 (n, length of given cterms which have been allified
       
   366  [| !! vs. P1 vs; !! vs. Pn vs |] ==> !! C vs) the allified thm
       
   367 *)
       
   368 (* note: C may contain further premices etc 
       
   369 Note that cterms is the assumed facts, ie prems of "P1" that are
       
   370 reintroduced in allified form.
       
   371 *)
       
   372 fun prepare_goal_export (vs, cterms) th = 
       
   373     let 
       
   374       val sgn = Thm.sign_of_thm th;
       
   375       val ctermify = Thm.cterm_of sgn;
       
   376 
       
   377       val allfrees = map Term.dest_Free (Term.term_frees (Thm.prop_of th))
       
   378       val cfrees = map (ctermify o Free o lookupfree allfrees) vs
       
   379 
       
   380       val sgs = prems_of th;
       
   381       val (sgallcts, sgthms) = 
       
   382           Library.split_list (map (allify_for_sg_term ctermify cfrees) sgs);
       
   383 
       
   384       val minimal_th = 
       
   385           Goal.conclude (Library.foldl (fn ( th', sgthm) => 
       
   386                           Drule.compose_single (sgthm, 1, th'))
       
   387                       (th, sgthms));
       
   388 
       
   389       val allified_th = 
       
   390           minimal_th 
       
   391             |> Drule.implies_intr_list cterms
       
   392             |> Drule.forall_intr_list cfrees 
       
   393 
       
   394       val th' = Drule.implies_intr_list sgallcts allified_th
       
   395     in
       
   396       ((length sgallcts), th')
       
   397     end;
       
   398 
       
   399 end;
       
   400 
       
   401 
       
   402 (* exporting function that takes a solution to the fixed/assumed goal,
       
   403 and uses this to solve the subgoal in the main theorem *)
       
   404 fun export_solution (export {fixes = cfvs, assumes = hcprems,
       
   405                              sgid = i, gth = gth}) solth = 
       
   406     let 
       
   407       val solth' = 
       
   408           solth |> Drule.implies_intr_list hcprems
       
   409                 |> Drule.forall_intr_list cfvs
       
   410     in Drule.compose_single (solth', i, gth) end;
       
   411 
       
   412 fun export_solutions (xs,th) = foldr (uncurry export_solution) th xs;
       
   413 
       
   414 
       
   415 (* fix parameters of a subgoal "i", as free variables, and create an
       
   416 exporting function that will use the result of this proved goal to
       
   417 show the goal in the original theorem. 
       
   418 
       
   419 Note, an advantage of this over Isar is that it supports instantiation
       
   420 of unkowns in the earlier theorem, ie we can do instantiation of meta
       
   421 vars! 
       
   422 
       
   423 avoids constant, free and vars names. 
       
   424 
       
   425 loosely corresponds to:
       
   426 Given "[| SG0; ... !! x. As ==> SGi x; ... SGm |] ==> G" : thm
       
   427 Result: 
       
   428   ("(As ==> SGi x') ==> (As ==> SGi x')" : thm, 
       
   429    expf : 
       
   430      ("As ==> SGi x'" : thm) -> 
       
   431      ("[| SG0; ... SGi-1; SGi+1; ... SGm |] ==> G") : thm)
       
   432 *)
       
   433 fun fix_alls_in_term alledt = 
       
   434     let
       
   435       val t = Term.strip_all_body alledt;
       
   436       val alls = rev (Term.strip_all_vars alledt);
       
   437       val varnames = map (fst o fst o Term.dest_Var) (Term.term_vars t)
       
   438       val names = Term.add_term_names (t,varnames);
       
   439       val fvs = map Free 
       
   440                     ((Term.variantlist (map fst alls, names)) 
       
   441                        ~~ (map snd alls));
       
   442     in ((subst_bounds (fvs,t)), fvs) end;
       
   443 
       
   444 fun fix_alls_term i t = 
       
   445     let 
       
   446       val varnames = map (fst o fst o Term.dest_Var) (Term.term_vars t)
       
   447       val names = Term.add_term_names (t,varnames);
       
   448       val gt = Logic.get_goal t i;
       
   449       val body = Term.strip_all_body gt;
       
   450       val alls = rev (Term.strip_all_vars gt);
       
   451       val fvs = map Free 
       
   452                     ((Term.variantlist (map fst alls, names)) 
       
   453                        ~~ (map snd alls));
       
   454     in ((subst_bounds (fvs,body)), fvs) end;
       
   455 
       
   456 fun fix_alls_cterm i th = 
       
   457     let
       
   458       val ctermify = Thm.cterm_of (Thm.sign_of_thm th);
       
   459       val (fixedbody, fvs) = fix_alls_term i (Thm.prop_of th);
       
   460       val cfvs = rev (map ctermify fvs);
       
   461       val ct_body = ctermify fixedbody
       
   462     in
       
   463       (ct_body, cfvs)
       
   464     end;
       
   465 
       
   466 fun fix_alls' i = 
       
   467      (apfst Thm.trivial) o (fix_alls_cterm i);
       
   468 
       
   469 
       
   470 (* hide other goals *) 
       
   471 (* note the export goal is rotated by (i - 1) and will have to be
       
   472 unrotated to get backto the originial position(s) *)
       
   473 fun hide_other_goals th = 
       
   474     let
       
   475       (* tl beacuse fst sg is the goal we are interested in *)
       
   476       val cprems = tl (Drule.cprems_of th)
       
   477       val aprems = map Thm.assume cprems
       
   478     in
       
   479       (Drule.implies_elim_list (Drule.rotate_prems 1 th) aprems, 
       
   480        cprems)
       
   481     end;
       
   482 
       
   483 (* a nicer version of the above that leaves only a single subgoal (the
       
   484 other subgoals are hidden hyps, that the exporter suffles about)
       
   485 namely the subgoal that we were trying to solve. *)
       
   486 (* loosely corresponds to:
       
   487 Given "[| SG0; ... !! x. As ==> SGi x; ... SGm |] ==> G" : thm
       
   488 Result: 
       
   489   ("(As ==> SGi x') ==> SGi x'" : thm, 
       
   490    expf : 
       
   491      ("SGi x'" : thm) -> 
       
   492      ("[| SG0; ... SGi-1; SGi+1; ... SGm |] ==> G") : thm)
       
   493 *)
       
   494 fun fix_alls i th = 
       
   495     let 
       
   496       val (fixed_gth, fixedvars) = fix_alls' i th
       
   497       val (sml_gth, othergoals) = hide_other_goals fixed_gth
       
   498     in
       
   499       (sml_gth, export {fixes = fixedvars, 
       
   500                         assumes = othergoals, 
       
   501                         sgid = i, gth = th})
       
   502     end;
       
   503 
       
   504 
       
   505 (* assume the premises of subgoal "i", this gives back a list of
       
   506 assumed theorems that are the premices of subgoal i, it also gives
       
   507 back a new goal thm and an exporter, the new goalthm is as the old
       
   508 one, but without the premices, and the exporter will use a proof of
       
   509 the new goalthm, possibly using the assumed premices, to shoe the
       
   510 orginial goal.
       
   511 
       
   512 Note: Dealing with meta vars, need to meta-level-all them in the
       
   513 shyps, which we can later instantiate with a specific value.... ? 
       
   514 think about this... maybe need to introduce some new fixed vars and
       
   515 then remove them again at the end... like I do with rw_inst. 
       
   516 
       
   517 loosely corresponds to:
       
   518 Given "[| SG0; ... [| A0; ... An |] ==> SGi; ... SGm |] ==> G" : thm
       
   519 Result: 
       
   520 (["A0" [A0], ... ,"An" [An]] : thm list, -- assumptions
       
   521  "SGi ==> SGi" : thm, -- new goal 
       
   522  "SGi" ["A0" ... "An"] : thm ->   -- export function
       
   523     ("[| SG0 ... SGi-1, SGi+1, SGm |] ==> G" : thm) list)
       
   524 *)
       
   525 fun assume_prems i th =
       
   526     let 
       
   527       val t = (prop_of th); 
       
   528       val gt = Logic.get_goal t i;
       
   529       val _ = case Term.strip_all_vars gt of [] => () 
       
   530               | _ => error "assume_prems: goal has params"
       
   531       val body = gt;
       
   532       val prems = Logic.strip_imp_prems body;
       
   533       val concl = Logic.strip_imp_concl body;
       
   534 
       
   535       val sgn = Thm.sign_of_thm th;
       
   536       val ctermify = Thm.cterm_of sgn;
       
   537       val cprems = map ctermify prems;
       
   538       val aprems = map Thm.assume cprems;
       
   539       val gthi = Thm.trivial (ctermify concl);
       
   540 
       
   541       (* fun explortf thi = 
       
   542           Drule.compose (Drule.implies_intr_list cprems thi, 
       
   543                          i, th) *)
       
   544     in
       
   545       (aprems, gthi, cprems)
       
   546     end;
       
   547 
       
   548 
       
   549 (* first fix the variables, then assume the assumptions *)
       
   550 (* loosely corresponds to:
       
   551 Given 
       
   552   "[| SG0; ... 
       
   553       !! xs. [| A0 xs; ... An xs |] ==> SGi xs; 
       
   554       ... SGm |] ==> G" : thm
       
   555 Result: 
       
   556 (["A0 xs'" [A0 xs'], ... ,"An xs'" [An xs']] : thm list, -- assumptions
       
   557  "SGi xs' ==> SGi xs'" : thm,  -- new goal 
       
   558  "SGi xs'" ["A0 xs'" ... "An xs'"] : thm ->   -- export function
       
   559     ("[| SG0 ... SGi-1, SGi+1, SGm |] ==> G" : thm) list)
       
   560 *)
       
   561 
       
   562 (* Note: the fix_alls actually pulls through all the assumptions which
       
   563 means that the second export is not needed. *)
       
   564 fun fixes_and_assumes i th = 
       
   565     let 
       
   566       val (fixgth, exp1) = fix_alls i th
       
   567       val (assumps, goalth, _) = assume_prems 1 fixgth
       
   568     in 
       
   569       (assumps, goalth, exp1)
       
   570     end;
       
   571 
       
   572 
       
   573 (* Fixme: allow different order of subgoals given to expf *)
       
   574 (* make each subgoal into a separate thm that needs to be proved *)
       
   575 (* loosely corresponds to:
       
   576 Given 
       
   577   "[| SG0; ... SGm |] ==> G" : thm
       
   578 Result: 
       
   579 (["SG0 ==> SG0", ... ,"SGm ==> SGm"] : thm list, -- goals
       
   580  ["SG0", ..., "SGm"] : thm list ->   -- export function
       
   581    "G" : thm)
       
   582 *)
       
   583 fun subgoal_thms th = 
       
   584     let 
       
   585       val t = (prop_of th); 
       
   586 
       
   587       val prems = Logic.strip_imp_prems t;
       
   588 
       
   589       val sgn = Thm.sign_of_thm th;
       
   590       val ctermify = Thm.cterm_of sgn;
       
   591 
       
   592       val aprems = map (Thm.trivial o ctermify) prems;
       
   593 
       
   594       fun explortf premths = 
       
   595           Drule.implies_elim_list th premths
       
   596     in
       
   597       (aprems, explortf)
       
   598     end;
       
   599 
       
   600 
       
   601 (* make all the premices of a theorem hidden, and provide an unhide
       
   602 function, that will bring them back out at a later point. This is
       
   603 useful if you want to get back these premices, after having used the
       
   604 theorem with the premices hidden *)
       
   605 (* loosely corresponds to:
       
   606 Given "As ==> G" : thm
       
   607 Result: ("G [As]" : thm, 
       
   608          "G [As]" : thm -> "As ==> G" : thm
       
   609 *)
       
   610 fun hide_prems th = 
       
   611     let 
       
   612       val cprems = Drule.cprems_of th;
       
   613       val aprems = map Thm.assume cprems;
       
   614     (*   val unhidef = Drule.implies_intr_list cprems; *)
       
   615     in
       
   616       (Drule.implies_elim_list th aprems, cprems)
       
   617     end;
       
   618 
       
   619 
       
   620 
       
   621 
       
   622 (* Fixme: allow different order of subgoals in exportf *)
       
   623 (* as above, but also fix all parameters in all subgoals, and uses
       
   624 fix_alls, not fix_alls', ie doesn't leave extra asumptions as apparent
       
   625 subgoals. *)
       
   626 (* loosely corresponds to:
       
   627 Given 
       
   628   "[| !! x0s. A0s x0s ==> SG0 x0s; 
       
   629       ...; !! xms. Ams xms ==> SGm xms|] ==> G" : thm
       
   630 Result: 
       
   631 (["(A0s x0s' ==> SG0 x0s') ==> SG0 x0s'", 
       
   632   ... ,"(Ams xms' ==> SGm xms') ==> SGm xms'"] : thm list, -- goals
       
   633  ["SG0 x0s'", ..., "SGm xms'"] : thm list ->   -- export function
       
   634    "G" : thm)
       
   635 *)
       
   636 (* requires being given solutions! *)
       
   637 fun fixed_subgoal_thms th = 
       
   638     let 
       
   639       val (subgoals, expf) = subgoal_thms th;
       
   640 (*       fun export_sg (th, exp) = exp th; *)
       
   641       fun export_sgs expfs solthms = 
       
   642           expf (map2 (curry (op |>)) solthms expfs);
       
   643 (*           expf (map export_sg (ths ~~ expfs)); *)
       
   644     in 
       
   645       apsnd export_sgs (Library.split_list (map (apsnd export_solution o 
       
   646                                                  fix_alls 1) subgoals))
       
   647     end;
       
   648 
       
   649 end;