src/Pure/Isar/proof.ML
author ballarin
Fri, 02 Apr 2004 14:08:30 +0200
changeset 14508 859b11514537
parent 14404 4952c5a92e04
child 14528 1457584110ac
permissions -rw-r--r--
Experimental command for instantiation of locales in proof contexts:
instantiate <label>: <loc>
     1 (*  Title:      Pure/Isar/proof.ML
     2     ID:         $Id$
     3     Author:     Markus Wenzel, TU Muenchen
     4     License:    GPL (GNU GENERAL PUBLIC LICENSE)
     5 
     6 Proof states and methods.
     7 *)
     8 
     9 signature BASIC_PROOF =
    10 sig
    11   val FINDGOAL: (int -> thm -> 'a Seq.seq) -> thm -> 'a Seq.seq
    12   val HEADGOAL: (int -> thm -> 'a Seq.seq) -> thm -> 'a Seq.seq
    13 end;
    14 
    15 signature PROOF =
    16 sig
    17   include BASIC_PROOF
    18   type context
    19   type state
    20   datatype mode = Forward | ForwardChain | Backward
    21   exception STATE of string * state
    22   val check_result: string -> state -> 'a Seq.seq -> 'a Seq.seq
    23   val init_state: theory -> state
    24   val context_of: state -> context
    25   val theory_of: state -> theory
    26   val sign_of: state -> Sign.sg
    27   val map_context: (context -> context) -> state -> state
    28   val warn_extra_tfrees: state -> state -> state
    29   val reset_thms: string -> state -> state
    30   val the_facts: state -> thm list
    31   val the_fact: state -> thm
    32   val get_goal: state -> context * (thm list * thm)
    33   val goal_facts: (state -> thm list) -> state -> state
    34   val use_facts: state -> state
    35   val reset_facts: state -> state
    36   val get_mode: state -> mode
    37   val is_chain: state -> bool
    38   val assert_forward: state -> state
    39   val assert_forward_or_chain: state -> state
    40   val assert_backward: state -> state
    41   val assert_no_chain: state -> state
    42   val enter_forward: state -> state
    43   val verbose: bool ref
    44   val show_main_goal: bool ref
    45   val pretty_state: int -> state -> Pretty.T list
    46   val pretty_goals: bool -> state -> Pretty.T list
    47   val level: state -> int
    48   type method
    49   val method: (thm list -> tactic) -> method
    50   val method_cases: (thm list -> thm -> (thm * (string * RuleCases.T) list) Seq.seq) -> method
    51   val refine: (context -> method) -> state -> state Seq.seq
    52   val refine_end: (context -> method) -> state -> state Seq.seq
    53   val match_bind: (string list * string) list -> state -> state
    54   val match_bind_i: (term list * term) list -> state -> state
    55   val let_bind: (string list * string) list -> state -> state
    56   val let_bind_i: (term list * term) list -> state -> state
    57   val simple_have_thms: string -> thm list -> state -> state
    58   val have_thmss: ((bstring * context attribute list) *
    59     (xstring * context attribute list) list) list -> state -> state
    60   val have_thmss_i: ((bstring * context attribute list) *
    61     (thm list * context attribute list) list) list -> state -> state
    62   val with_thmss: ((bstring * context attribute list) *
    63     (xstring * context attribute list) list) list -> state -> state
    64   val with_thmss_i: ((bstring * context attribute list) *
    65     (thm list * context attribute list) list) list -> state -> state
    66   val using_thmss: ((xstring * context attribute list) list) list -> state -> state
    67   val using_thmss_i: ((thm list * context attribute list) list) list -> state -> state
    68   val instantiate_locale: string * string -> state -> state
    69   val fix: (string list * string option) list -> state -> state
    70   val fix_i: (string list * typ option) list -> state -> state
    71   val assm: ProofContext.exporter
    72     -> ((string * context attribute list) * (string * (string list * string list)) list) list
    73     -> state -> state
    74   val assm_i: ProofContext.exporter
    75     -> ((string * context attribute list) * (term * (term list * term list)) list) list
    76     -> state -> state
    77   val assume:
    78     ((string * context attribute list) * (string * (string list * string list)) list) list
    79     -> state -> state
    80   val assume_i: ((string * context attribute list) * (term * (term list * term list)) list) list
    81     -> state -> state
    82   val presume:
    83     ((string * context attribute list) * (string * (string list * string list)) list) list
    84     -> state -> state
    85   val presume_i: ((string * context attribute list) * (term * (term list * term list)) list) list
    86     -> state -> state
    87   val def: string -> context attribute list -> string *  (string * string list) -> state -> state
    88   val def_i: string -> context attribute list -> string * (term * term list) -> state -> state
    89   val invoke_case: string * string option list * context attribute list -> state -> state
    90   val multi_theorem: string
    91     -> (xstring * (context attribute list * context attribute list list)) option
    92     -> bstring * theory attribute list -> context attribute Locale.element list
    93     -> ((bstring * theory attribute list) * (string * (string list * string list)) list) list
    94     -> theory -> state
    95   val multi_theorem_i: string
    96     -> (string * (context attribute list * context attribute list list)) option
    97     -> bstring * theory attribute list
    98     -> context attribute Locale.element_i list
    99     -> ((bstring * theory attribute list) * (term * (term list * term list)) list) list
   100     -> theory -> state
   101   val chain: state -> state
   102   val from_facts: thm list -> state -> state
   103   val show: (bool -> state -> state) -> (state -> state Seq.seq) -> bool
   104     -> ((string * context attribute list) * (string * (string list * string list)) list) list
   105     -> bool -> state -> state
   106   val show_i: (bool -> state -> state) -> (state -> state Seq.seq) -> bool
   107     -> ((string * context attribute list) * (term * (term list * term list)) list) list
   108     -> bool -> state -> state
   109   val have: (state -> state Seq.seq) -> bool
   110     -> ((string * context attribute list) * (string * (string list * string list)) list) list
   111     -> state -> state
   112   val have_i: (state -> state Seq.seq) -> bool
   113     -> ((string * context attribute list) * (term * (term list * term list)) list) list
   114     -> state -> state
   115   val at_bottom: state -> bool
   116   val local_qed: (state -> state Seq.seq)
   117     -> (context -> string * (string * thm list) list -> unit) * (context -> thm -> unit)
   118     -> state -> state Seq.seq
   119   val global_qed: (state -> state Seq.seq) -> state
   120     -> (theory * ((string * string) * (string * thm list) list)) Seq.seq
   121   val begin_block: state -> state
   122   val end_block: state -> state Seq.seq
   123   val next_block: state -> state
   124 end;
   125 
   126 structure Proof: PROOF =
   127 struct
   128 
   129 
   130 (** proof state **)
   131 
   132 type context = ProofContext.context;
   133 
   134 
   135 (* type goal *)
   136 
   137 datatype kind =
   138   Theorem of {kind: string,
   139     theory_spec: (bstring * theory attribute list) * theory attribute list list,
   140     locale_spec: (string * (context attribute list * context attribute list list)) option,
   141     view: cterm list} |
   142   Show of context attribute list list |
   143   Have of context attribute list list;
   144 
   145 fun kind_name _ (Theorem {kind = s, theory_spec = ((a, _), _),
   146         locale_spec = None, view = _}) = s ^ (if a = "" then "" else " " ^ a)
   147   | kind_name sg (Theorem {kind = s, theory_spec = ((a, _), _),
   148         locale_spec = Some (name, _), view = _}) =
   149       s ^ " (in " ^ Locale.cond_extern sg name ^ ")" ^ (if a = "" then "" else " " ^ a)
   150   | kind_name _ (Show _) = "show"
   151   | kind_name _ (Have _) = "have";
   152 
   153 type goal =
   154  (kind *             (*result kind*)
   155   string list *      (*result names*)
   156   term list list) *  (*result statements*)
   157  (thm list *         (*use facts*)
   158   thm);              (*goal: subgoals ==> statement*)
   159 
   160 
   161 (* type mode *)
   162 
   163 datatype mode = Forward | ForwardChain | Backward;
   164 val mode_name = (fn Forward => "state" | ForwardChain => "chain" | Backward => "prove");
   165 
   166 
   167 (* datatype state *)
   168 
   169 datatype node =
   170   Node of
   171    {context: context,
   172     facts: thm list option,
   173     mode: mode,
   174     goal: (goal * ((state -> state Seq.seq) * bool)) option}
   175 and state =
   176   State of
   177     node *              (*current*)
   178     node list;          (*parents wrt. block structure*)
   179 
   180 fun make_node (context, facts, mode, goal) =
   181   Node {context = context, facts = facts, mode = mode, goal = goal};
   182 
   183 
   184 exception STATE of string * state;
   185 
   186 fun err_malformed name state =
   187   raise STATE (name ^ ": internal error -- malformed proof state", state);
   188 
   189 fun check_result msg state sq =
   190   (case Seq.pull sq of
   191     None => raise STATE (msg, state)
   192   | Some s_sq => Seq.cons s_sq);
   193 
   194 
   195 fun map_current f (State (Node {context, facts, mode, goal}, nodes)) =
   196   State (make_node (f (context, facts, mode, goal)), nodes);
   197 
   198 fun init_state thy =
   199   State (make_node (ProofContext.init thy, None, Forward, None), []);
   200 
   201 
   202 
   203 (** basic proof state operations **)
   204 
   205 (* context *)
   206 
   207 fun context_of (State (Node {context, ...}, _)) = context;
   208 val theory_of = ProofContext.theory_of o context_of;
   209 val sign_of = ProofContext.sign_of o context_of;
   210 
   211 fun map_context f = map_current (fn (ctxt, facts, mode, goal) => (f ctxt, facts, mode, goal));
   212 
   213 fun map_context_result f (state as State (Node {context, facts, mode, goal}, nodes)) =
   214   let val (context', result) = f context
   215   in (State (make_node (context', facts, mode, goal), nodes), result) end;
   216 
   217 
   218 val warn_extra_tfrees = map_context o ProofContext.warn_extra_tfrees o context_of;
   219 val add_binds_i = map_context o ProofContext.add_binds_i;
   220 val auto_bind_goal = map_context o ProofContext.auto_bind_goal;
   221 val auto_bind_facts = map_context o ProofContext.auto_bind_facts;
   222 val put_thms = map_context o ProofContext.put_thms;
   223 val put_thmss = map_context o ProofContext.put_thmss;
   224 val reset_thms = map_context o ProofContext.reset_thms;
   225 val get_case = ProofContext.get_case o context_of;
   226 
   227 
   228 (* facts *)
   229 
   230 fun the_facts (State (Node {facts = Some facts, ...}, _)) = facts
   231   | the_facts state = raise STATE ("No current facts available", state);
   232 
   233 fun the_fact state =
   234   (case the_facts state of
   235     [thm] => thm
   236   | _ => raise STATE ("Single fact expected", state));
   237 
   238 fun assert_facts state = (the_facts state; state);
   239 fun get_facts (State (Node {facts, ...}, _)) = facts;
   240 
   241 
   242 val thisN = "this";
   243 
   244 fun put_facts facts state =
   245   state
   246   |> map_current (fn (ctxt, _, mode, goal) => (ctxt, facts, mode, goal))
   247   |> (case facts of None => reset_thms thisN | Some ths => put_thms (thisN, ths));
   248 
   249 val reset_facts = put_facts None;
   250 
   251 fun these_factss (state, named_factss) =
   252   state |> put_facts (Some (flat (map snd named_factss)));
   253 
   254 
   255 (* goal *)
   256 
   257 local
   258   fun find i (state as State (Node {goal = Some goal, ...}, _)) = (context_of state, (i, goal))
   259     | find i (State (Node {goal = None, ...}, node :: nodes)) = find (i + 1) (State (node, nodes))
   260     | find _ (state as State (_, [])) = err_malformed "find_goal" state;
   261 in val find_goal = find 0 end;
   262 
   263 fun get_goal state =
   264   let val (ctxt, (_, ((_, x), _))) = find_goal state
   265   in (ctxt, x) end;
   266 
   267 fun put_goal goal = map_current (fn (ctxt, facts, mode, _) => (ctxt, facts, mode, goal));
   268 
   269 fun map_goal f g (State (Node {context, facts, mode, goal = Some goal}, nodes)) =
   270       State (make_node (f context, facts, mode, Some (g goal)), nodes)
   271   | map_goal f g (State (nd, node :: nodes)) =
   272       let val State (node', nodes') = map_goal f g (State (node, nodes))
   273       in map_context f (State (nd, node' :: nodes')) end
   274   | map_goal _ _ state = state;
   275 
   276 fun goal_facts get state =
   277   state
   278   |> map_goal I (fn ((result, (_, thm)), f) => ((result, (get state, thm)), f));
   279 
   280 fun use_facts state =
   281   state
   282   |> goal_facts the_facts
   283   |> reset_facts;
   284 
   285 
   286 (* mode *)
   287 
   288 fun get_mode (State (Node {mode, ...}, _)) = mode;
   289 fun put_mode mode = map_current (fn (ctxt, facts, _, goal) => (ctxt, facts, mode, goal));
   290 
   291 val enter_forward = put_mode Forward;
   292 val enter_forward_chain = put_mode ForwardChain;
   293 val enter_backward = put_mode Backward;
   294 
   295 fun assert_mode pred state =
   296   let val mode = get_mode state in
   297     if pred mode then state
   298     else raise STATE ("Illegal application of proof command in "
   299       ^ quote (mode_name mode) ^ " mode", state)
   300   end;
   301 
   302 fun is_chain state = get_mode state = ForwardChain;
   303 val assert_forward = assert_mode (equal Forward);
   304 val assert_forward_or_chain = assert_mode (equal Forward orf equal ForwardChain);
   305 val assert_backward = assert_mode (equal Backward);
   306 val assert_no_chain = assert_mode (not_equal ForwardChain);
   307 
   308 
   309 (* blocks *)
   310 
   311 fun level (State (_, nodes)) = length nodes;
   312 
   313 fun open_block (State (node, nodes)) = State (node, node :: nodes);
   314 
   315 fun new_block state =
   316   state
   317   |> open_block
   318   |> put_goal None;
   319 
   320 fun close_block (state as State (_, node :: nodes)) = State (node, nodes)
   321   | close_block state = raise STATE ("Unbalanced block parentheses", state);
   322 
   323 
   324 
   325 (** pretty_state **)
   326 
   327 val show_main_goal = ref false;
   328 
   329 val verbose = ProofContext.verbose;
   330 
   331 fun pretty_goals_local ctxt = Display.pretty_goals_aux
   332   (ProofContext.pretty_sort ctxt, ProofContext.pretty_typ ctxt, ProofContext.pretty_term ctxt);
   333 
   334 fun pretty_facts _ _ None = []
   335   | pretty_facts s ctxt (Some ths) =
   336       [Pretty.big_list (s ^ "this:") (map (ProofContext.pretty_thm ctxt) ths), Pretty.str ""];
   337 
   338 fun pretty_state nr (state as State (Node {context = ctxt, facts, mode, goal = _}, nodes)) =
   339   let
   340     val ref (_, _, begin_goal) = Display.current_goals_markers;
   341 
   342     fun levels_up 0 = ""
   343       | levels_up 1 = ", 1 level up"
   344       | levels_up i = ", " ^ string_of_int i ^ " levels up";
   345 
   346     fun subgoals 0 = ""
   347       | subgoals 1 = ", 1 subgoal"
   348       | subgoals n = ", " ^ string_of_int n ^ " subgoals";
   349 
   350     fun prt_names names =
   351       (case filter_out (equal "") names of [] => ""
   352       | nms => " " ^ enclose "(" ")" (space_implode " and " (take (7, nms) @
   353           (if length nms > 7 then ["..."] else []))));
   354 
   355     fun prt_goal (_, (i, (((kind, names, _), (goal_facts, thm)), _))) =
   356       pretty_facts "using " ctxt
   357         (if mode <> Backward orelse null goal_facts then None else Some goal_facts) @
   358       [Pretty.str ("goal (" ^ kind_name (sign_of state) kind ^ prt_names names ^
   359           levels_up (i div 2) ^ subgoals (Thm.nprems_of thm) ^ "):")] @
   360       pretty_goals_local ctxt begin_goal (true, !show_main_goal) (! Display.goals_limit) thm;
   361 
   362     val ctxt_prts =
   363       if ! verbose orelse mode = Forward then ProofContext.pretty_context ctxt
   364       else if mode = Backward then ProofContext.pretty_asms ctxt
   365       else [];
   366 
   367     val prts =
   368      [Pretty.str ("proof (" ^ mode_name mode ^ "): step " ^ string_of_int nr ^
   369         (if ! verbose then ", depth " ^ string_of_int (length nodes div 2 - 1)
   370         else "")), Pretty.str ""] @
   371      (if null ctxt_prts then [] else ctxt_prts @ [Pretty.str ""]) @
   372      (if ! verbose orelse mode = Forward then
   373        (pretty_facts "" ctxt facts @ prt_goal (find_goal state))
   374       else if mode = ForwardChain then pretty_facts "picking " ctxt facts
   375       else prt_goal (find_goal state))
   376   in prts end;
   377 
   378 fun pretty_goals main state =
   379   let val (ctxt, (_, ((_, (_, thm)), _))) = find_goal state
   380   in pretty_goals_local ctxt "" (false, main) (! Display.goals_limit) thm end;
   381 
   382 
   383 
   384 (** proof steps **)
   385 
   386 (* datatype method *)
   387 
   388 datatype method =
   389   Method of thm list -> thm -> (thm * (string * RuleCases.T) list) Seq.seq;
   390 
   391 fun method tac = Method (fn facts => fn st => Seq.map (rpair []) (tac facts st));
   392 val method_cases = Method;
   393 
   394 
   395 (* refine goal *)
   396 
   397 local
   398 
   399 fun check_sign sg state =
   400   if Sign.subsig (sg, sign_of state) then state
   401   else raise STATE ("Bad signature of result: " ^ Sign.str_of_sg sg, state);
   402 
   403 fun gen_refine current_context meth_fun state =
   404   let
   405     val (goal_ctxt, (_, ((result, (facts, thm)), x))) = find_goal state;
   406     val Method meth = meth_fun (if current_context then context_of state else goal_ctxt);
   407 
   408     fun refn (thm', cases) =
   409       state
   410       |> check_sign (Thm.sign_of_thm thm')
   411       |> map_goal (ProofContext.add_cases cases) (K ((result, (facts, thm')), x));
   412   in Seq.map refn (meth facts thm) end;
   413 
   414 in
   415 
   416 val refine = gen_refine true;
   417 val refine_end = gen_refine false;
   418 
   419 end;
   420 
   421 
   422 (* goal addressing *)
   423 
   424 fun FINDGOAL tac st =
   425   let fun find (i, n) = if i > n then Seq.fail else Seq.APPEND (tac i, find (i + 1, n))
   426   in find (1, Thm.nprems_of st) st end;
   427 
   428 fun HEADGOAL tac = tac 1;
   429 
   430 
   431 (* export results *)
   432 
   433 fun refine_tac rule =
   434   Tactic.norm_hhf_tac THEN' Tactic.rtac rule THEN_ALL_NEW (SUBGOAL (fn (goal, i) =>
   435     if can Logic.dest_goal (Logic.strip_assums_concl goal) then
   436       Tactic.etac Drule.triv_goal i
   437     else all_tac));
   438 
   439 fun export_goal inner print_rule raw_rule state =
   440   let
   441     val (outer, (_, ((result, (facts, thm)), x))) = find_goal state;
   442     val exp_tac = ProofContext.export true inner outer;
   443     fun exp_rule rule =
   444       let
   445         val _ = print_rule outer rule;
   446         val thmq = FINDGOAL (refine_tac rule) thm;
   447       in Seq.map (fn th => map_goal I (K ((result, (facts, th)), x)) state) thmq end;
   448   in raw_rule |> exp_tac |> (Seq.flat o Seq.map exp_rule) end;
   449 
   450 fun export_goals inner print_rule raw_rules =
   451   Seq.EVERY (map (export_goal inner print_rule) raw_rules);
   452 
   453 fun transfer_facts inner_state state =
   454   (case get_facts inner_state of
   455     None => Seq.single (reset_facts state)
   456   | Some thms =>
   457       let
   458         val exp_tac = ProofContext.export false (context_of inner_state) (context_of state);
   459         val thmqs = map exp_tac thms;
   460       in Seq.map (fn ths => put_facts (Some ths) state) (Seq.commute thmqs) end);
   461 
   462 
   463 (* prepare result *)
   464 
   465 fun prep_result state ts raw_th =
   466   let
   467     val ctxt = context_of state;
   468     fun err msg = raise STATE (msg, state);
   469 
   470     val ngoals = Thm.nprems_of raw_th;
   471     val _ =
   472       if ngoals = 0 then ()
   473       else (err (Pretty.string_of (Pretty.chunks (pretty_goals_local ctxt "" (true, !show_main_goal)
   474             (! Display.goals_limit) raw_th @
   475           [Pretty.str (string_of_int ngoals ^ " unsolved goal(s)!")]))));
   476 
   477     val {hyps, sign, ...} = Thm.rep_thm raw_th;
   478     val tsig = Sign.tsig_of sign;
   479     val casms = flat (map #1 (ProofContext.assumptions_of (context_of state)));
   480     val bad_hyps = Library.gen_rems Term.aconv (hyps, map Thm.term_of casms);
   481 
   482     val th = raw_th RS Drule.rev_triv_goal;
   483     val ths = Drule.conj_elim_precise (length ts) th
   484       handle THM _ => err "Main goal structure corrupted";
   485   in
   486     conditional (not (null bad_hyps)) (fn () => err ("Additional hypotheses:\n" ^
   487         cat_lines (map (ProofContext.string_of_term ctxt) bad_hyps)));
   488     conditional (exists (not o Pattern.matches tsig) (ts ~~ map Thm.prop_of ths)) (fn () =>
   489       err ("Proved a different theorem: " ^ Pretty.string_of (ProofContext.pretty_thm ctxt th)));
   490     ths
   491   end;
   492 
   493 
   494 
   495 (*** structured proof commands ***)
   496 
   497 (** context **)
   498 
   499 (* bind *)
   500 
   501 fun gen_bind f x state =
   502   state
   503   |> assert_forward
   504   |> map_context (f x)
   505   |> reset_facts;
   506 
   507 val match_bind = gen_bind (ProofContext.match_bind false);
   508 val match_bind_i = gen_bind (ProofContext.match_bind_i false);
   509 val let_bind = gen_bind (ProofContext.match_bind true);
   510 val let_bind_i = gen_bind (ProofContext.match_bind_i true);
   511 
   512 
   513 (* have_thmss *)
   514 (* CB: this implements "note" of the Isar/VM *)
   515 
   516 local
   517 
   518 fun gen_have_thmss f args state =
   519   state
   520   |> assert_forward
   521   |> map_context_result (f args)
   522   |> these_factss;
   523 
   524 in
   525 
   526 val have_thmss = gen_have_thmss ProofContext.have_thmss;
   527 val have_thmss_i = gen_have_thmss ProofContext.have_thmss_i;
   528 
   529 fun simple_have_thms name thms = have_thmss_i [((name, []), [(thms, [])])];
   530 
   531 end;
   532 
   533 
   534 (* with_thmss *)
   535 
   536 local
   537 
   538 fun gen_with_thmss f args state =
   539   let val state' = state |> f args
   540   in state' |> simple_have_thms "" (the_facts state' @ the_facts state) end;
   541 
   542 in
   543 
   544 val with_thmss = gen_with_thmss have_thmss;
   545 val with_thmss_i = gen_with_thmss have_thmss_i;
   546 
   547 end;
   548 
   549 
   550 (* using_thmss *)
   551 
   552 local
   553 
   554 fun gen_using_thmss f args state =
   555   state
   556   |> assert_backward
   557   |> map_context_result (f (map (pair ("", [])) args))
   558   |> (fn (st, named_facts) =>
   559     let val (_, (_, ((result, (facts, thm)), x))) = find_goal st;
   560     in st |> map_goal I (K ((result, (facts @ flat (map snd named_facts), thm)), x)) end);
   561 
   562 in
   563 
   564 val using_thmss = gen_using_thmss ProofContext.have_thmss;
   565 val using_thmss_i = gen_using_thmss ProofContext.have_thmss_i;
   566 
   567 end;
   568 
   569 
   570 (* locale instantiation *)
   571 
   572 fun instantiate_locale (loc_name, prfx) state = let
   573     val ctxt = context_of state;
   574     val facts = if is_chain state then get_facts state else None;
   575   in
   576     state
   577     |> assert_forward_or_chain
   578     |> enter_forward
   579     |> reset_facts
   580     |> map_context (Locale.instantiate loc_name prfx facts)
   581   end;
   582 
   583 (* fix *)
   584 
   585 fun gen_fix f xs state =
   586   state
   587   |> assert_forward
   588   |> map_context (f xs)
   589   |> reset_facts;
   590 
   591 val fix = gen_fix ProofContext.fix;
   592 val fix_i = gen_fix ProofContext.fix_i;
   593 
   594 
   595 (* assume and presume *)
   596 
   597 fun gen_assume f exp args state =
   598   state
   599   |> assert_forward
   600   |> map_context_result (f exp args)
   601   |> these_factss;
   602 
   603 val assm = gen_assume ProofContext.assume;
   604 val assm_i = gen_assume ProofContext.assume_i;
   605 val assume = assm ProofContext.export_assume;
   606 val assume_i = assm_i ProofContext.export_assume;
   607 val presume = assm ProofContext.export_presume;
   608 val presume_i = assm_i ProofContext.export_presume;
   609 
   610 
   611 
   612 (** local definitions **)
   613 
   614 fun gen_def fix prep_term prep_pats raw_name atts (x, (raw_rhs, raw_pats)) state =
   615   let
   616     val _ = assert_forward state;
   617     val ctxt = context_of state;
   618 
   619     (*rhs*)
   620     val name = if raw_name = "" then Thm.def_name x else raw_name;
   621     val rhs = prep_term ctxt raw_rhs;
   622     val T = Term.fastype_of rhs;
   623     val pats = prep_pats T (ProofContext.declare_term rhs ctxt) raw_pats;
   624 
   625     (*lhs*)
   626     val lhs = ProofContext.bind_skolem ctxt [x] (Free (x, T));
   627   in
   628     state
   629     |> fix [([x], None)]
   630     |> match_bind_i [(pats, rhs)]
   631     |> assm_i ProofContext.export_def [((name, atts), [(Logic.mk_equals (lhs, rhs), ([], []))])]
   632   end;
   633 
   634 val def = gen_def fix ProofContext.read_term ProofContext.read_term_pats;
   635 val def_i = gen_def fix_i ProofContext.cert_term ProofContext.cert_term_pats;
   636 
   637 
   638 (* invoke_case *)
   639 
   640 fun invoke_case (name, xs, atts) state =
   641   let
   642     val (state', (lets, asms)) =
   643       map_context_result (ProofContext.apply_case (get_case state name xs)) state;
   644     val assumptions = asms |> map (fn (a, ts) =>
   645       ((if a = "" then "" else NameSpace.append name a, atts), map (rpair ([], [])) ts));
   646     val qnames = filter_out (equal "") (map (#1 o #1) assumptions);
   647   in
   648     state'
   649     |> add_binds_i lets
   650     |> map_context (ProofContext.qualified true)
   651     |> assume_i assumptions
   652     |> map_context (ProofContext.hide_thms false qnames)
   653     |> (fn st => simple_have_thms name (the_facts st) st)
   654     |> map_context (ProofContext.restore_qualified (context_of state))
   655   end;
   656 
   657 
   658 
   659 (** goals **)
   660 
   661 (* forward chaining *)
   662 
   663 fun chain state =
   664   state
   665   |> assert_forward
   666   |> assert_facts
   667   |> enter_forward_chain;
   668 
   669 fun from_facts facts state =
   670   state
   671   |> put_facts (Some facts)
   672   |> chain;
   673 
   674 
   675 (* setup goals *)
   676 
   677 val rule_contextN = "rule_context";
   678 
   679 fun setup_goal opt_block prepp autofix kind after_qed pr names raw_propp state =
   680   let
   681     val (state', (propss, gen_binds)) =
   682       state
   683       |> assert_forward_or_chain
   684       |> enter_forward
   685       |> opt_block
   686       |> map_context_result (fn ctxt => prepp (ctxt, raw_propp));
   687     val sign' = sign_of state';
   688 
   689     val props = flat propss;
   690     val cprop = Thm.cterm_of sign' (Logic.mk_conjunction_list props);
   691     val goal = Drule.mk_triv_goal cprop;
   692 
   693     val tvars = foldr Term.add_term_tvars (props, []);
   694     val vars = foldr Term.add_term_vars (props, []);
   695   in
   696     if null tvars then ()
   697     else raise STATE ("Goal statement contains illegal schematic type variable(s): " ^
   698       commas (map (Syntax.string_of_vname o #1) tvars), state);
   699     if null vars then ()
   700     else warning ("Goal statement contains unbound schematic variable(s): " ^
   701       commas (map (ProofContext.string_of_term (context_of state')) vars));
   702     state'
   703     |> map_context (autofix props)
   704     |> put_goal (Some (((kind, names, propss), ([], goal)),
   705       (after_qed o map_context gen_binds, pr)))
   706     |> map_context (ProofContext.add_cases
   707      (if length props = 1 then
   708       RuleCases.make true None (Thm.sign_of_thm goal, Thm.prop_of goal) [rule_contextN]
   709       else [(rule_contextN, RuleCases.empty)]))
   710     |> auto_bind_goal props
   711     |> (if is_chain state then use_facts else reset_facts)
   712     |> new_block
   713     |> enter_backward
   714   end;
   715 
   716 (*global goals*)
   717 fun global_goal prep kind raw_locale a elems concl thy =
   718   let
   719     val init = init_state thy;
   720     val (opt_name, view, locale_ctxt, elems_ctxt, propp) =
   721       prep (apsome fst raw_locale) elems (map snd concl) (context_of init);
   722   in
   723     init
   724     |> open_block
   725     |> map_context (K locale_ctxt)
   726     |> open_block
   727     |> map_context (K elems_ctxt)
   728     |> setup_goal I ProofContext.bind_propp_schematic_i ProofContext.fix_frees
   729       (Theorem {kind = kind,
   730         theory_spec = (a, map (snd o fst) concl),
   731         locale_spec = (case raw_locale of None => None | Some (_, x) => Some (the opt_name, x)),
   732         view = view})
   733       Seq.single true (map (fst o fst) concl) propp
   734   end;
   735 
   736 val multi_theorem = global_goal Locale.read_context_statement;
   737 val multi_theorem_i = global_goal Locale.cert_context_statement;
   738 
   739 
   740 (*local goals*)
   741 fun local_goal' prepp kind (check: bool -> state -> state) f pr args int state =
   742   state
   743   |> setup_goal open_block prepp (K I) (kind (map (snd o fst) args))
   744     f pr (map (fst o fst) args) (map snd args)
   745   |> warn_extra_tfrees state
   746   |> check int;
   747 
   748 fun local_goal prepp kind f pr args = local_goal' prepp kind (K I) f pr args false;
   749 
   750 val show = local_goal' ProofContext.bind_propp Show;
   751 val show_i = local_goal' ProofContext.bind_propp_i Show;
   752 val have = local_goal ProofContext.bind_propp Have;
   753 val have_i = local_goal ProofContext.bind_propp_i Have;
   754 
   755 
   756 
   757 (** conclusions **)
   758 
   759 (* current goal *)
   760 
   761 fun current_goal (State (Node {context, goal = Some goal, ...}, _)) = (context, goal)
   762   | current_goal state = raise STATE ("No current goal!", state);
   763 
   764 fun assert_current_goal true (state as State (Node {goal = None, ...}, _)) =
   765       raise STATE ("No goal in this block!", state)
   766   | assert_current_goal false (state as State (Node {goal = Some _, ...}, _)) =
   767       raise STATE ("Goal present in this block!", state)
   768   | assert_current_goal _ state = state;
   769 
   770 fun assert_bottom b (state as State (_, nodes)) =
   771   let val bot = (length nodes <= 2) in
   772     if b andalso not bot then raise STATE ("Not at bottom of proof!", state)
   773     else if not b andalso bot then raise STATE ("Already at bottom of proof!", state)
   774     else state
   775   end;
   776 
   777 val at_bottom = can (assert_bottom true o close_block);
   778 
   779 fun end_proof bot state =
   780   state
   781   |> assert_forward
   782   |> close_block
   783   |> assert_bottom bot
   784   |> assert_current_goal true
   785   |> goal_facts (K []);
   786 
   787 
   788 (* local_qed *)
   789 
   790 fun finish_local (print_result, print_rule) state =
   791   let
   792     val (goal_ctxt, (((kind, names, tss), (_, raw_thm)), (after_qed, pr))) = current_goal state;
   793     val outer_state = state |> close_block;
   794     val outer_ctxt = context_of outer_state;
   795 
   796     val ts = flat tss;
   797     val results = prep_result state ts raw_thm;
   798     val resultq =
   799       results |> map (ProofContext.export false goal_ctxt outer_ctxt)
   800       |> Seq.commute |> Seq.map (Library.unflat tss);
   801 
   802     val (attss, opt_solve) =
   803       (case kind of
   804         Show attss => (attss,
   805           export_goals goal_ctxt (if pr then print_rule else (K (K ()))) results)
   806       | Have attss => (attss, Seq.single)
   807       | _ => err_malformed "finish_local" state);
   808   in
   809     conditional pr (fn () => print_result goal_ctxt
   810       (kind_name (sign_of state) kind, names ~~ Library.unflat tss results));
   811     outer_state
   812     |> auto_bind_facts (ProofContext.generalize goal_ctxt outer_ctxt ts)
   813     |> (fn st => Seq.map (fn res =>
   814       have_thmss_i ((names ~~ attss) ~~ map (single o Thm.no_attributes) res) st) resultq)
   815     |> (Seq.flat o Seq.map opt_solve)
   816     |> (Seq.flat o Seq.map after_qed)
   817   end;
   818 
   819 fun local_qed finalize print state =
   820   state
   821   |> end_proof false
   822   |> finalize
   823   |> (Seq.flat o Seq.map (finish_local print));
   824 
   825 
   826 (* global_qed *)
   827 
   828 fun finish_global state =
   829   let
   830     val (goal_ctxt, (((kind, names, tss), (_, raw_thm)), _)) = current_goal state;
   831     val locale_ctxt = context_of (state |> close_block);
   832     val theory_ctxt = context_of (state |> close_block |> close_block);
   833     val {kind = k, theory_spec = ((name, atts), attss), locale_spec, view} =
   834       (case kind of Theorem x => x | _ => err_malformed "finish_global" state);
   835 
   836     val ts = flat tss;
   837     val locale_results = map (ProofContext.export_standard [] goal_ctxt locale_ctxt)
   838       (prep_result state ts raw_thm);
   839 
   840     val locale_results' = map
   841       (Locale.prune_prems (ProofContext.theory_of locale_ctxt))
   842       locale_results;
   843 
   844     val results = map (Drule.strip_shyps_warning o
   845       ProofContext.export_standard view locale_ctxt theory_ctxt) locale_results';
   846 
   847     val (theory', results') =
   848       theory_of state
   849       |> (case locale_spec of None => I | Some (loc, (loc_atts, loc_attss)) => fn thy =>
   850         if length names <> length loc_attss then
   851           raise THEORY ("Bad number of locale attributes", [thy])
   852         else (thy, locale_ctxt)
   853           |> Locale.add_thmss loc ((names ~~ Library.unflat tss locale_results') ~~ loc_attss)
   854           |> (fn ((thy', ctxt'), res) =>
   855             if name = "" andalso null loc_atts then thy'
   856             else (thy', ctxt')
   857               |> (#1 o #1 o Locale.add_thmss loc [((name, flat (map #2 res)), loc_atts)])))
   858       |> Locale.smart_have_thmss k locale_spec
   859         ((names ~~ attss) ~~ map (single o Thm.no_attributes) (Library.unflat tss results))
   860       |> (fn (thy, res) => (thy, res)
   861           |>> (#1 o Locale.smart_have_thmss k locale_spec
   862             [((name, atts), [(flat (map #2 res), [])])]));
   863   in (theory', ((k, name), results')) end;
   864 
   865 
   866 (*note: clients should inspect first result only, as backtracking may destroy theory*)
   867 fun global_qed finalize state =
   868   state
   869   |> end_proof true
   870   |> finalize
   871   |> Seq.map finish_global;
   872 
   873 
   874 
   875 (** blocks **)
   876 
   877 (* begin_block *)
   878 
   879 fun begin_block state =
   880   state
   881   |> assert_forward
   882   |> new_block
   883   |> open_block;
   884 
   885 
   886 (* end_block *)
   887 
   888 fun end_block state =
   889   state
   890   |> assert_forward
   891   |> close_block
   892   |> assert_current_goal false
   893   |> close_block
   894   |> transfer_facts state;
   895 
   896 
   897 (* next_block *)
   898 
   899 fun next_block state =
   900   state
   901   |> assert_forward
   902   |> close_block
   903   |> new_block
   904   |> reset_facts;
   905 
   906 
   907 end;
   908 
   909 structure BasicProof: BASIC_PROOF = Proof;
   910 open BasicProof;