| author | paulson | 
| Tue, 28 Feb 2006 11:07:54 +0100 | |
| changeset 19153 | 0864119a9611 | 
| parent 19100 | 644a7a47ed02 | 
| child 19188 | a4c82a9ff7d8 | 
| permissions | -rw-r--r-- | 
| 5820 | 1 | (* Title: Pure/Isar/proof.ML | 
| 2 | ID: $Id$ | |
| 3 | Author: Markus Wenzel, TU Muenchen | |
| 4 | ||
| 19000 | 5 | The Isar/VM proof language interpreter: maintains a structured flow of | 
| 6 | context elements, goals, refinements, and facts. | |
| 5820 | 7 | *) | 
| 8 | ||
| 9 | signature PROOF = | |
| 10 | sig | |
| 17756 | 11 | type context (*= Context.proof*) | 
| 12 | type method (*= Method.method*) | |
| 5820 | 13 | type state | 
| 17359 | 14 | val init: context -> state | 
| 15 | val level: state -> int | |
| 16 | val assert_bottom: bool -> state -> state | |
| 5820 | 17 | val context_of: state -> context | 
| 18 | val theory_of: state -> theory | |
| 16450 | 19 | val sign_of: state -> theory (*obsolete*) | 
| 13377 | 20 | val map_context: (context -> context) -> state -> state | 
| 7924 | 21 | val warn_extra_tfrees: state -> state -> state | 
| 17976 | 22 | val add_binds_i: (indexname * term option) list -> state -> state | 
| 19078 | 23 | val put_thms: bool -> string * thm list option -> state -> state | 
| 24 | val put_thms_internal: string * thm list option -> state -> state | |
| 6091 | 25 | val the_facts: state -> thm list | 
| 9469 | 26 | val the_fact: state -> thm | 
| 17450 | 27 | val put_facts: thm list option -> state -> state | 
| 6891 | 28 | val assert_forward: state -> state | 
| 17359 | 29 | val assert_chain: state -> state | 
| 9469 | 30 | val assert_forward_or_chain: state -> state | 
| 5820 | 31 | val assert_backward: state -> state | 
| 8206 | 32 | val assert_no_chain: state -> state | 
| 5820 | 33 | val enter_forward: state -> state | 
| 17359 | 34 | val get_goal: state -> context * (thm list * thm) | 
| 16539 | 35 | val show_main_goal: bool ref | 
| 6529 | 36 | val verbose: bool ref | 
| 12423 | 37 | val pretty_state: int -> state -> Pretty.T list | 
| 10360 | 38 | val pretty_goals: bool -> state -> Pretty.T list | 
| 17112 | 39 | val refine: Method.text -> state -> state Seq.seq | 
| 40 | val refine_end: Method.text -> state -> state Seq.seq | |
| 18908 | 41 | val refine_insert: thm list -> state -> state | 
| 17359 | 42 | val refine_goals: (context -> thm -> unit) -> context -> thm list -> state -> state Seq.seq | 
| 5936 | 43 | val match_bind: (string list * string) list -> state -> state | 
| 44 | val match_bind_i: (term list * term) list -> state -> state | |
| 8617 
33e2bd53aec3
support Hindley-Milner polymorphisms in binds and facts;
 wenzelm parents: 
8582diff
changeset | 45 | val let_bind: (string list * string) list -> state -> state | 
| 
33e2bd53aec3
support Hindley-Milner polymorphisms in binds and facts;
 wenzelm parents: 
8582diff
changeset | 46 | val let_bind_i: (term list * term) list -> state -> state | 
| 18670 | 47 | val fix: (string * string option) list -> state -> state | 
| 48 | val fix_i: (string * typ option) list -> state -> state | |
| 49 | val assm: ProofContext.export -> | |
| 17359 | 50 | ((string * Attrib.src list) * (string * (string list * string list)) list) list -> | 
| 51 | state -> state | |
| 18670 | 52 | val assm_i: ProofContext.export -> | 
| 18728 | 53 | ((string * attribute list) * (term * (term list * term list)) list) list | 
| 17359 | 54 | -> state -> state | 
| 55 | val assume: ((string * Attrib.src list) * (string * (string list * string list)) list) list -> | |
| 56 | state -> state | |
| 18728 | 57 | val assume_i: ((string * attribute list) * (term * (term list * term list)) list) list | 
| 17359 | 58 | -> state -> state | 
| 59 | val presume: ((string * Attrib.src list) * (string * (string list * string list)) list) list | |
| 60 | -> state -> state | |
| 18728 | 61 | val presume_i: ((string * attribute list) * (term * (term list * term list)) list) list | 
| 17359 | 62 | -> state -> state | 
| 18308 | 63 | val def: ((string * Attrib.src list) * (string * (string * string list))) list -> | 
| 64 | state -> state | |
| 18728 | 65 | val def_i: ((string * attribute list) * (string * (term * term list))) list -> | 
| 18308 | 66 | state -> state | 
| 17359 | 67 | val chain: state -> state | 
| 68 | val chain_facts: thm list -> state -> state | |
| 69 | val get_thmss: state -> (thmref * Attrib.src list) list -> thm list | |
| 14564 | 70 | val simple_note_thms: string -> thm list -> state -> state | 
| 17359 | 71 | val note_thmss: ((string * Attrib.src list) * | 
| 17112 | 72 | (thmref * Attrib.src list) list) list -> state -> state | 
| 18728 | 73 | val note_thmss_i: ((string * attribute list) * | 
| 74 | (thm list * attribute list) list) list -> state -> state | |
| 17112 | 75 | val from_thmss: ((thmref * Attrib.src list) list) list -> state -> state | 
| 18728 | 76 | val from_thmss_i: ((thm list * attribute list) list) list -> state -> state | 
| 17112 | 77 | val with_thmss: ((thmref * Attrib.src list) list) list -> state -> state | 
| 18728 | 78 | val with_thmss_i: ((thm list * attribute list) list) list -> state -> state | 
| 18548 | 79 | val using: ((thmref * Attrib.src list) list) list -> state -> state | 
| 18728 | 80 | val using_i: ((thm list * attribute list) list) list -> state -> state | 
| 18548 | 81 | val unfolding: ((thmref * Attrib.src list) list) list -> state -> state | 
| 18728 | 82 | val unfolding_i: ((thm list * attribute list) list) list -> state -> state | 
| 17112 | 83 | val invoke_case: string * string option list * Attrib.src list -> state -> state | 
| 18728 | 84 | val invoke_case_i: string * string option list * attribute list -> state -> state | 
| 17359 | 85 | val begin_block: state -> state | 
| 86 | val next_block: state -> state | |
| 87 | val end_block: state -> state Seq.seq | |
| 17112 | 88 | val proof: Method.text option -> state -> state Seq.seq | 
| 89 | val defer: int option -> state -> state Seq.seq | |
| 90 | val prefer: int -> state -> state Seq.seq | |
| 91 | val apply: Method.text -> state -> state Seq.seq | |
| 92 | val apply_end: Method.text -> state -> state Seq.seq | |
| 17359 | 93 | val goal_names: string option -> string -> string list -> string | 
| 94 | val local_goal: (context -> ((string * string) * (string * thm list) list) -> unit) -> | |
| 18728 | 95 | (theory -> 'a -> attribute) -> | 
| 17359 | 96 | (context * 'b list -> context * (term list list * (context -> context))) -> | 
| 18124 | 97 | string -> Method.text option -> (thm list list -> state -> state Seq.seq) -> | 
| 17359 | 98 | ((string * 'a list) * 'b) list -> state -> state | 
| 99 | val local_qed: Method.text option * bool -> state -> state Seq.seq | |
| 100 | val global_goal: (context -> (string * string) * (string * thm list) list -> unit) -> | |
| 18728 | 101 | (theory -> 'a -> attribute) -> | 
| 17450 | 102 | (context * 'b list -> context * (term list list * (context -> context))) -> | 
| 18124 | 103 | string -> Method.text option -> (thm list list -> theory -> theory) -> | 
| 17859 | 104 | string option -> string * 'a list -> ((string * 'a list) * 'b) list -> context -> state | 
| 18808 | 105 | val global_qed: Method.text option * bool -> state -> context * theory | 
| 17359 | 106 | val local_terminal_proof: Method.text * Method.text option -> state -> state Seq.seq | 
| 107 | val local_default_proof: state -> state Seq.seq | |
| 108 | val local_immediate_proof: state -> state Seq.seq | |
| 109 | val local_done_proof: state -> state Seq.seq | |
| 110 | val local_skip_proof: bool -> state -> state Seq.seq | |
| 18808 | 111 | val global_terminal_proof: Method.text * Method.text option -> state -> context * theory | 
| 112 | val global_default_proof: state -> context * theory | |
| 113 | val global_immediate_proof: state -> context * theory | |
| 114 | val global_done_proof: state -> context * theory | |
| 115 | val global_skip_proof: bool -> state -> context * theory | |
| 18124 | 116 | val have: Method.text option -> (thm list list -> state -> state Seq.seq) -> | 
| 17359 | 117 | ((string * Attrib.src list) * (string * (string list * string list)) list) list -> | 
| 118 | bool -> state -> state | |
| 18124 | 119 | val have_i: Method.text option -> (thm list list -> state -> state Seq.seq) -> | 
| 18728 | 120 | ((string * attribute list) * (term * (term list * term list)) list) list -> | 
| 17359 | 121 | bool -> state -> state | 
| 18124 | 122 | val show: Method.text option -> (thm list list -> state -> state Seq.seq) -> | 
| 17359 | 123 | ((string * Attrib.src list) * (string * (string list * string list)) list) list -> | 
| 124 | bool -> state -> state | |
| 18124 | 125 | val show_i: Method.text option -> (thm list list -> state -> state Seq.seq) -> | 
| 18728 | 126 | ((string * attribute list) * (term * (term list * term list)) list) list -> | 
| 17359 | 127 | bool -> state -> state | 
| 18124 | 128 | val theorem: string -> Method.text option -> (thm list list -> theory -> theory) -> | 
| 17359 | 129 | string option -> string * Attrib.src list -> | 
| 130 | ((string * Attrib.src list) * (string * (string list * string list)) list) list -> | |
| 131 | context -> state | |
| 18124 | 132 | val theorem_i: string -> Method.text option -> (thm list list -> theory -> theory) -> | 
| 18728 | 133 | string option -> string * attribute list -> | 
| 134 | ((string * attribute list) * (term * (term list * term list)) list) list -> | |
| 17359 | 135 | context -> state | 
| 5820 | 136 | end; | 
| 137 | ||
| 13377 | 138 | structure Proof: PROOF = | 
| 5820 | 139 | struct | 
| 140 | ||
| 16813 | 141 | type context = ProofContext.context; | 
| 17112 | 142 | type method = Method.method; | 
| 16813 | 143 | |
| 5820 | 144 | |
| 145 | (** proof state **) | |
| 146 | ||
| 17359 | 147 | (* datatype state *) | 
| 5820 | 148 | |
| 17112 | 149 | datatype mode = Forward | Chain | Backward; | 
| 5820 | 150 | |
| 17359 | 151 | datatype state = | 
| 152 | State of node Stack.T | |
| 153 | and node = | |
| 7176 | 154 | Node of | 
| 155 |    {context: context,
 | |
| 156 | facts: thm list option, | |
| 157 | mode: mode, | |
| 17359 | 158 | goal: goal option} | 
| 159 | and goal = | |
| 160 | Goal of | |
| 161 |    {statement: string * term list list,     (*goal kind and statement*)
 | |
| 162 | using: thm list, (*goal facts*) | |
| 163 | goal: thm, (*subgoals ==> statement*) | |
| 17859 | 164 | before_qed: Method.text option, | 
| 18124 | 165 | after_qed: | 
| 166 | (thm list list -> state -> state Seq.seq) * | |
| 167 | (thm list list -> theory -> theory)}; | |
| 17359 | 168 | |
| 17859 | 169 | fun make_goal (statement, using, goal, before_qed, after_qed) = | 
| 170 |   Goal {statement = statement, using = using, goal = goal,
 | |
| 171 | before_qed = before_qed, after_qed = after_qed}; | |
| 5820 | 172 | |
| 7176 | 173 | fun make_node (context, facts, mode, goal) = | 
| 174 |   Node {context = context, facts = facts, mode = mode, goal = goal};
 | |
| 175 | ||
| 17359 | 176 | fun map_node f (Node {context, facts, mode, goal}) =
 | 
| 177 | make_node (f (context, facts, mode, goal)); | |
| 5820 | 178 | |
| 17359 | 179 | fun init ctxt = State (Stack.init (make_node (ctxt, NONE, Forward, NONE))); | 
| 5820 | 180 | |
| 17359 | 181 | fun current (State st) = Stack.top st |> (fn Node node => node); | 
| 182 | fun map_current f (State st) = State (Stack.map (map_node f) st); | |
| 12045 | 183 | |
| 5820 | 184 | |
| 185 | ||
| 186 | (** basic proof state operations **) | |
| 187 | ||
| 17359 | 188 | (* block structure *) | 
| 189 | ||
| 190 | fun open_block (State st) = State (Stack.push st); | |
| 191 | ||
| 18678 | 192 | fun close_block (State st) = State (Stack.pop st) | 
| 193 | handle Empty => error "Unbalanced block parentheses"; | |
| 17359 | 194 | |
| 195 | fun level (State st) = Stack.level st; | |
| 196 | ||
| 197 | fun assert_bottom b state = | |
| 198 | let val b' = (level state <= 2) in | |
| 18678 | 199 | if b andalso not b' then error "Not at bottom of proof!" | 
| 200 | else if not b andalso b' then error "Already at bottom of proof!" | |
| 17359 | 201 | else state | 
| 202 | end; | |
| 203 | ||
| 204 | ||
| 5820 | 205 | (* context *) | 
| 206 | ||
| 17359 | 207 | val context_of = #context o current; | 
| 5820 | 208 | val theory_of = ProofContext.theory_of o context_of; | 
| 16450 | 209 | val sign_of = theory_of; | 
| 5820 | 210 | |
| 17359 | 211 | fun map_context f = | 
| 212 | map_current (fn (ctxt, facts, mode, goal) => (f ctxt, facts, mode, goal)); | |
| 5820 | 213 | |
| 17359 | 214 | fun map_context_result f state = | 
| 17859 | 215 | f (context_of state) ||> (fn ctxt => map_context (K ctxt) state); | 
| 5820 | 216 | |
| 7924 | 217 | val warn_extra_tfrees = map_context o ProofContext.warn_extra_tfrees o context_of; | 
| 10809 | 218 | val add_binds_i = map_context o ProofContext.add_binds_i; | 
| 19078 | 219 | val put_thms = map_context oo ProofContext.put_thms; | 
| 220 | val put_thms_internal = map_context o ProofContext.put_thms_internal; | |
| 5820 | 221 | |
| 222 | ||
| 223 | (* facts *) | |
| 224 | ||
| 17359 | 225 | val get_facts = #facts o current; | 
| 226 | ||
| 227 | fun the_facts state = | |
| 228 | (case get_facts state of SOME facts => facts | |
| 18678 | 229 | | NONE => error "No current facts available"); | 
| 5820 | 230 | |
| 9469 | 231 | fun the_fact state = | 
| 17359 | 232 | (case the_facts state of [thm] => thm | 
| 18678 | 233 | | _ => error "Single theorem expected"); | 
| 7605 | 234 | |
| 17359 | 235 | fun put_facts facts = | 
| 19078 | 236 | map_current (fn (ctxt, _, mode, goal) => (ctxt, facts, mode, goal)) #> | 
| 237 | put_thms_internal (AutoBind.thisN, facts); | |
| 5820 | 238 | |
| 17359 | 239 | fun these_factss more_facts (named_factss, state) = | 
| 240 | (named_factss, state |> put_facts (SOME (List.concat (map snd named_factss) @ more_facts))); | |
| 5820 | 241 | |
| 17359 | 242 | fun export_facts inner outer = | 
| 243 | (case get_facts inner of | |
| 244 | NONE => Seq.single (put_facts NONE outer) | |
| 245 | | SOME thms => | |
| 246 | thms | |
| 18041 
052622286158
renamed Goal constant to prop, more general protect/unprotect interfaces;
 wenzelm parents: 
17976diff
changeset | 247 | |> Seq.map_list (ProofContext.exports (context_of inner) (context_of outer)) | 
| 17359 | 248 | |> Seq.map (fn ths => put_facts (SOME ths) outer)); | 
| 5820 | 249 | |
| 250 | ||
| 251 | (* mode *) | |
| 252 | ||
| 17359 | 253 | val get_mode = #mode o current; | 
| 5820 | 254 | fun put_mode mode = map_current (fn (ctxt, facts, _, goal) => (ctxt, facts, mode, goal)); | 
| 255 | ||
| 17359 | 256 | val mode_name = (fn Forward => "state" | Chain => "chain" | Backward => "prove"); | 
| 5820 | 257 | |
| 258 | fun assert_mode pred state = | |
| 259 | let val mode = get_mode state in | |
| 260 | if pred mode then state | |
| 18678 | 261 |     else error ("Illegal application of proof command in " ^ quote (mode_name mode) ^ " mode")
 | 
| 5820 | 262 | end; | 
| 263 | ||
| 264 | val assert_forward = assert_mode (equal Forward); | |
| 17359 | 265 | val assert_chain = assert_mode (equal Chain); | 
| 17112 | 266 | val assert_forward_or_chain = assert_mode (equal Forward orf equal Chain); | 
| 5820 | 267 | val assert_backward = assert_mode (equal Backward); | 
| 17112 | 268 | val assert_no_chain = assert_mode (not_equal Chain); | 
| 5820 | 269 | |
| 17359 | 270 | val enter_forward = put_mode Forward; | 
| 271 | val enter_chain = put_mode Chain; | |
| 272 | val enter_backward = put_mode Backward; | |
| 5820 | 273 | |
| 17359 | 274 | |
| 275 | (* current goal *) | |
| 276 | ||
| 277 | fun current_goal state = | |
| 278 | (case current state of | |
| 279 |     {context, goal = SOME (Goal goal), ...} => (context, goal)
 | |
| 18678 | 280 | | _ => error "No current goal!"); | 
| 5820 | 281 | |
| 17359 | 282 | fun assert_current_goal g state = | 
| 283 | let val g' = can current_goal state in | |
| 18678 | 284 | if g andalso not g' then error "No goal in this block!" | 
| 285 | else if not g andalso g' then error "Goal present in this block!" | |
| 17359 | 286 | else state | 
| 287 | end; | |
| 6776 | 288 | |
| 17359 | 289 | fun put_goal goal = map_current (fn (ctxt, using, mode, _) => (ctxt, using, mode, goal)); | 
| 290 | ||
| 17859 | 291 | val before_qed = #before_qed o #2 o current_goal; | 
| 292 | ||
| 17359 | 293 | |
| 294 | (* nested goal *) | |
| 5820 | 295 | |
| 17359 | 296 | fun map_goal f g (State (Node {context, facts, mode, goal = SOME goal}, nodes)) =
 | 
| 297 | let | |
| 17859 | 298 |         val Goal {statement, using, goal, before_qed, after_qed} = goal;
 | 
| 299 | val goal' = make_goal (g (statement, using, goal, before_qed, after_qed)); | |
| 17359 | 300 | in State (make_node (f context, facts, mode, SOME goal'), nodes) end | 
| 301 | | map_goal f g (State (nd, node :: nodes)) = | |
| 302 | let val State (node', nodes') = map_goal f g (State (node, nodes)) | |
| 303 | in map_context f (State (nd, node' :: nodes')) end | |
| 304 | | map_goal _ _ state = state; | |
| 5820 | 305 | |
| 17859 | 306 | fun using_facts using = map_goal I (fn (statement, _, goal, before_qed, after_qed) => | 
| 307 | (statement, using, goal, before_qed, after_qed)); | |
| 17359 | 308 | |
| 309 | local | |
| 310 | fun find i state = | |
| 311 | (case try current_goal state of | |
| 312 | SOME (ctxt, goal) => (ctxt, (i, goal)) | |
| 18678 | 313 | | NONE => find (i + 1) (close_block state handle ERROR _ => error "No goal present")); | 
| 17359 | 314 | in val find_goal = find 0 end; | 
| 315 | ||
| 316 | fun get_goal state = | |
| 317 |   let val (ctxt, (_, {using, goal, ...})) = find_goal state
 | |
| 318 | in (ctxt, (using, goal)) end; | |
| 5820 | 319 | |
| 320 | ||
| 321 | ||
| 12423 | 322 | (** pretty_state **) | 
| 5820 | 323 | |
| 13869 | 324 | val show_main_goal = ref false; | 
| 16539 | 325 | val verbose = ProofContext.verbose; | 
| 13698 | 326 | |
| 14876 | 327 | val pretty_goals_local = Display.pretty_goals_aux o ProofContext.pp; | 
| 12085 | 328 | |
| 15531 | 329 | fun pretty_facts _ _ NONE = [] | 
| 330 | | pretty_facts s ctxt (SOME ths) = | |
| 12055 | 331 | [Pretty.big_list (s ^ "this:") (map (ProofContext.pretty_thm ctxt) ths), Pretty.str ""]; | 
| 6756 | 332 | |
| 17359 | 333 | fun pretty_state nr state = | 
| 5820 | 334 | let | 
| 17359 | 335 |     val {context, facts, mode, goal = _} = current state;
 | 
| 336 | val ref (_, _, bg) = Display.current_goals_markers; | |
| 5820 | 337 | |
| 338 | fun levels_up 0 = "" | |
| 17359 | 339 | | levels_up 1 = "1 level up" | 
| 340 | | levels_up i = string_of_int i ^ " levels up"; | |
| 5820 | 341 | |
| 11556 | 342 | fun subgoals 0 = "" | 
| 17359 | 343 | | subgoals 1 = "1 subgoal" | 
| 344 | | subgoals n = string_of_int n ^ " subgoals"; | |
| 345 | ||
| 346 | fun description strs = | |
| 347 | (case filter_out (equal "") strs of [] => "" | |
| 348 |       | strs' => enclose " (" ")" (commas strs'));
 | |
| 12146 | 349 | |
| 17859 | 350 |     fun prt_goal (SOME (ctxt, (i, {statement = (kind, _), using, goal, before_qed, after_qed}))) =
 | 
| 17359 | 351 | pretty_facts "using " ctxt | 
| 352 | (if mode <> Backward orelse null using then NONE else SOME using) @ | |
| 353 |           [Pretty.str ("goal" ^ description [kind, levels_up (i div 2),
 | |
| 354 | subgoals (Thm.nprems_of goal)] ^ ":")] @ | |
| 355 | pretty_goals_local ctxt bg (true, ! show_main_goal) (! Display.goals_limit) goal | |
| 356 | | prt_goal NONE = []; | |
| 6848 | 357 | |
| 17359 | 358 | val prt_ctxt = | 
| 359 | if ! verbose orelse mode = Forward then ProofContext.pretty_context context | |
| 18670 | 360 | else if mode = Backward then ProofContext.pretty_ctxt context | 
| 7575 | 361 | else []; | 
| 17359 | 362 | in | 
| 363 |     [Pretty.str ("proof (" ^ mode_name mode ^ "): step " ^ string_of_int nr ^
 | |
| 364 | (if ! verbose then ", depth " ^ string_of_int (level state div 2 - 1) else "")), | |
| 365 | Pretty.str ""] @ | |
| 366 | (if null prt_ctxt then [] else prt_ctxt @ [Pretty.str ""]) @ | |
| 367 | (if ! verbose orelse mode = Forward then | |
| 368 | pretty_facts "" context facts @ prt_goal (try find_goal state) | |
| 369 | else if mode = Chain then pretty_facts "picking " context facts | |
| 370 | else prt_goal (try find_goal state)) | |
| 371 | end; | |
| 5820 | 372 | |
| 12085 | 373 | fun pretty_goals main state = | 
| 17359 | 374 |   let val (ctxt, (_, {goal, ...})) = find_goal state
 | 
| 375 | in pretty_goals_local ctxt "" (false, main) (! Display.goals_limit) goal end; | |
| 10320 | 376 | |
| 5820 | 377 | |
| 378 | ||
| 379 | (** proof steps **) | |
| 380 | ||
| 17359 | 381 | (* refine via method *) | 
| 5820 | 382 | |
| 8234 | 383 | local | 
| 384 | ||
| 16146 | 385 | fun goalN i = "goal" ^ string_of_int i; | 
| 386 | fun goals st = map goalN (1 upto Thm.nprems_of st); | |
| 387 | ||
| 388 | fun no_goal_cases st = map (rpair NONE) (goals st); | |
| 389 | ||
| 390 | fun goal_cases st = | |
| 18607 | 391 | RuleCases.make_common true (Thm.theory_of_thm st, Thm.prop_of st) (map (rpair []) (goals st)); | 
| 16146 | 392 | |
| 16450 | 393 | fun check_theory thy state = | 
| 394 | if subthy (thy, theory_of state) then state | |
| 18678 | 395 |   else error ("Bad theory of method result: " ^ Context.str_of_thy thy);
 | 
| 5820 | 396 | |
| 17112 | 397 | fun apply_method current_context meth_fun state = | 
| 6848 | 398 | let | 
| 17859 | 399 |     val (goal_ctxt, (_, {statement, using, goal, before_qed, after_qed})) = find_goal state;
 | 
| 17112 | 400 | val meth = meth_fun (if current_context then context_of state else goal_ctxt); | 
| 16146 | 401 | in | 
| 18228 | 402 | Method.apply meth using goal |> Seq.map (fn (meth_cases, goal') => | 
| 6848 | 403 | state | 
| 17359 | 404 | |> check_theory (Thm.theory_of_thm goal') | 
| 16146 | 405 | |> map_goal | 
| 18475 | 406 | (ProofContext.add_cases false (no_goal_cases goal @ goal_cases goal') #> | 
| 407 | ProofContext.add_cases true meth_cases) | |
| 17859 | 408 | (K (statement, using, goal', before_qed, after_qed))) | 
| 16146 | 409 | end; | 
| 5820 | 410 | |
| 17112 | 411 | fun apply_text cc text state = | 
| 412 | let | |
| 413 | val thy = theory_of state; | |
| 414 | ||
| 415 | fun eval (Method.Basic m) = apply_method cc m | |
| 416 | | eval (Method.Source src) = apply_method cc (Method.method thy src) | |
| 417 | | eval (Method.Then txts) = Seq.EVERY (map eval txts) | |
| 418 | | eval (Method.Orelse txts) = Seq.FIRST (map eval txts) | |
| 419 | | eval (Method.Try txt) = Seq.TRY (eval txt) | |
| 420 | | eval (Method.Repeat1 txt) = Seq.REPEAT1 (eval txt); | |
| 421 | in eval text state end; | |
| 422 | ||
| 8234 | 423 | in | 
| 424 | ||
| 17112 | 425 | val refine = apply_text true; | 
| 426 | val refine_end = apply_text false; | |
| 8234 | 427 | |
| 18908 | 428 | fun refine_insert [] = I | 
| 429 | | refine_insert ths = Seq.hd o refine (Method.Basic (K (Method.insert ths))); | |
| 430 | ||
| 8234 | 431 | end; | 
| 432 | ||
| 5820 | 433 | |
| 17359 | 434 | (* refine via sub-proof *) | 
| 435 | ||
| 436 | local | |
| 9469 | 437 | |
| 11816 | 438 | fun refine_tac rule = | 
| 18186 | 439 | Tactic.norm_hhf_tac THEN' Tactic.rtac rule THEN_ALL_NEW | 
| 440 | (Tactic.norm_hhf_tac THEN' (SUBGOAL (fn (goal, i) => | |
| 441 | if can Logic.unprotect (Logic.strip_assums_concl goal) then | |
| 442 | Tactic.etac Drule.protectI i | |
| 443 | else all_tac))); | |
| 11816 | 444 | |
| 17359 | 445 | fun refine_goal print_rule inner raw_rule state = | 
| 17859 | 446 |   let val (outer, (_, {statement, using, goal, before_qed, after_qed})) = find_goal state in
 | 
| 17359 | 447 | raw_rule | 
| 18041 
052622286158
renamed Goal constant to prop, more general protect/unprotect interfaces;
 wenzelm parents: 
17976diff
changeset | 448 | |> ProofContext.goal_exports inner outer | 
| 17359 | 449 | |> Seq.maps (fn rule => | 
| 450 | (print_rule outer rule; | |
| 451 | goal | |
| 452 | |> FINDGOAL (refine_tac rule) | |
| 17859 | 453 | |> Seq.map (fn goal' => | 
| 454 | map_goal I (K (statement, using, goal', before_qed, after_qed)) state))) | |
| 17359 | 455 | end; | 
| 6932 | 456 | |
| 17359 | 457 | in | 
| 12146 | 458 | |
| 17359 | 459 | fun refine_goals print_rule inner raw_rules = | 
| 460 | Seq.EVERY (map (refine_goal print_rule inner) raw_rules); | |
| 461 | ||
| 462 | end; | |
| 6932 | 463 | |
| 464 | ||
| 17359 | 465 | (* conclude_goal *) | 
| 6932 | 466 | |
| 18503 
841137f20307
goal/qed: proper treatment of two levels of conjunctions;
 wenzelm parents: 
18475diff
changeset | 467 | fun conclude_goal state goal propss = | 
| 5820 | 468 | let | 
| 469 | val ctxt = context_of state; | |
| 470 | ||
| 17359 | 471 | val ngoals = Thm.nprems_of goal; | 
| 472 | val _ = conditional (ngoals > 0) (fn () => | |
| 18678 | 473 | error (Pretty.string_of (Pretty.chunks | 
| 17359 | 474 | (pretty_goals_local ctxt "" (true, ! show_main_goal) (! Display.goals_limit) goal @ | 
| 12085 | 475 | [Pretty.str (string_of_int ngoals ^ " unsolved goal(s)!")])))); | 
| 5820 | 476 | |
| 17359 | 477 |     val {hyps, thy, ...} = Thm.rep_thm goal;
 | 
| 17450 | 478 | val bad_hyps = fold (remove (op aconv)) (ProofContext.assms_of ctxt) hyps; | 
| 18678 | 479 |     val _ = conditional (not (null bad_hyps)) (fn () => error ("Additional hypotheses:\n" ^
 | 
| 18503 
841137f20307
goal/qed: proper treatment of two levels of conjunctions;
 wenzelm parents: 
18475diff
changeset | 480 | cat_lines (map (ProofContext.string_of_term ctxt) bad_hyps))); | 
| 12146 | 481 | |
| 17976 | 482 | val th = Goal.conclude goal; | 
| 18503 
841137f20307
goal/qed: proper treatment of two levels of conjunctions;
 wenzelm parents: 
18475diff
changeset | 483 | val _ = conditional (not (Pattern.matches thy | 
| 
841137f20307
goal/qed: proper treatment of two levels of conjunctions;
 wenzelm parents: 
18475diff
changeset | 484 | (Logic.mk_conjunction_list2 propss, Thm.prop_of th))) (fn () => | 
| 18678 | 485 |       error ("Proved a different theorem:\n" ^ ProofContext.string_of_thm ctxt th));
 | 
| 18503 
841137f20307
goal/qed: proper treatment of two levels of conjunctions;
 wenzelm parents: 
18475diff
changeset | 486 | in Drule.conj_elim_precise (map length propss) th end; | 
| 5820 | 487 | |
| 488 | ||
| 489 | ||
| 490 | (*** structured proof commands ***) | |
| 491 | ||
| 17112 | 492 | (** context elements **) | 
| 5820 | 493 | |
| 17112 | 494 | (* bindings *) | 
| 5820 | 495 | |
| 16813 | 496 | local | 
| 497 | ||
| 17359 | 498 | fun gen_bind bind args state = | 
| 5820 | 499 | state | 
| 500 | |> assert_forward | |
| 18308 | 501 | |> map_context (bind args #> snd) | 
| 17359 | 502 | |> put_facts NONE; | 
| 5820 | 503 | |
| 16813 | 504 | in | 
| 505 | ||
| 8617 
33e2bd53aec3
support Hindley-Milner polymorphisms in binds and facts;
 wenzelm parents: 
8582diff
changeset | 506 | val match_bind = gen_bind (ProofContext.match_bind false); | 
| 
33e2bd53aec3
support Hindley-Milner polymorphisms in binds and facts;
 wenzelm parents: 
8582diff
changeset | 507 | val match_bind_i = gen_bind (ProofContext.match_bind_i false); | 
| 
33e2bd53aec3
support Hindley-Milner polymorphisms in binds and facts;
 wenzelm parents: 
8582diff
changeset | 508 | val let_bind = gen_bind (ProofContext.match_bind true); | 
| 
33e2bd53aec3
support Hindley-Milner polymorphisms in binds and facts;
 wenzelm parents: 
8582diff
changeset | 509 | val let_bind_i = gen_bind (ProofContext.match_bind_i true); | 
| 5820 | 510 | |
| 16813 | 511 | end; | 
| 512 | ||
| 5820 | 513 | |
| 17359 | 514 | (* fix *) | 
| 9196 | 515 | |
| 12714 | 516 | local | 
| 517 | ||
| 18670 | 518 | fun gen_fix add_fixes args = | 
| 17359 | 519 | assert_forward | 
| 18670 | 520 | #> map_context (snd o add_fixes (map Syntax.no_syn args)) | 
| 17359 | 521 | #> put_facts NONE; | 
| 5820 | 522 | |
| 16813 | 523 | in | 
| 524 | ||
| 18670 | 525 | val fix = gen_fix ProofContext.add_fixes; | 
| 526 | val fix_i = gen_fix ProofContext.add_fixes_i; | |
| 5820 | 527 | |
| 16813 | 528 | end; | 
| 529 | ||
| 5820 | 530 | |
| 17359 | 531 | (* assume etc. *) | 
| 5820 | 532 | |
| 16813 | 533 | local | 
| 534 | ||
| 17112 | 535 | fun gen_assume asm prep_att exp args state = | 
| 5820 | 536 | state | 
| 537 | |> assert_forward | |
| 17112 | 538 | |> map_context_result (asm exp (Attrib.map_specs (prep_att (theory_of state)) args)) | 
| 17359 | 539 | |> these_factss [] |> #2; | 
| 6932 | 540 | |
| 16813 | 541 | in | 
| 542 | ||
| 18728 | 543 | val assm = gen_assume ProofContext.add_assms Attrib.attribute; | 
| 18670 | 544 | val assm_i = gen_assume ProofContext.add_assms_i (K I); | 
| 545 | val assume = assm ProofContext.assume_export; | |
| 546 | val assume_i = assm_i ProofContext.assume_export; | |
| 547 | val presume = assm ProofContext.presume_export; | |
| 548 | val presume_i = assm_i ProofContext.presume_export; | |
| 5820 | 549 | |
| 16813 | 550 | end; | 
| 551 | ||
| 7271 | 552 | |
| 17359 | 553 | (* def *) | 
| 11891 | 554 | |
| 16813 | 555 | local | 
| 556 | ||
| 18308 | 557 | fun gen_def fix prep_att prep_binds args state = | 
| 11891 | 558 | let | 
| 559 | val _ = assert_forward state; | |
| 17112 | 560 | val thy = theory_of state; | 
| 11891 | 561 | |
| 18308 | 562 | val ((raw_names, raw_atts), (xs, raw_rhss)) = args |> split_list |>> split_list ||> split_list; | 
| 563 |     val names = map (fn ("", x) => Thm.def_name x | (name, _) => name) (raw_names ~~ xs);
 | |
| 564 | val atts = map (map (prep_att thy)) raw_atts; | |
| 565 | val (rhss, state') = state |> map_context_result (prep_binds false (map swap raw_rhss)); | |
| 18826 | 566 | val eqs = LocalDefs.mk_def (context_of state') (xs ~~ rhss); | 
| 11891 | 567 | in | 
| 18308 | 568 | state' | 
| 18670 | 569 | |> fix (map (rpair NONE) xs) | 
| 18826 | 570 | |> assm_i LocalDefs.def_export ((names ~~ atts) ~~ map (fn eq => [(eq, ([], []))]) eqs) | 
| 11891 | 571 | end; | 
| 572 | ||
| 16813 | 573 | in | 
| 574 | ||
| 18728 | 575 | val def = gen_def fix Attrib.attribute ProofContext.match_bind; | 
| 18308 | 576 | val def_i = gen_def fix_i (K I) ProofContext.match_bind_i; | 
| 11891 | 577 | |
| 16813 | 578 | end; | 
| 579 | ||
| 11891 | 580 | |
| 8374 | 581 | |
| 17112 | 582 | (** facts **) | 
| 5820 | 583 | |
| 17359 | 584 | (* chain *) | 
| 5820 | 585 | |
| 17359 | 586 | val chain = | 
| 587 | assert_forward | |
| 588 | #> tap the_facts | |
| 589 | #> enter_chain; | |
| 5820 | 590 | |
| 17359 | 591 | fun chain_facts facts = | 
| 592 | put_facts (SOME facts) | |
| 593 | #> chain; | |
| 5820 | 594 | |
| 595 | ||
| 17359 | 596 | (* note etc. *) | 
| 17112 | 597 | |
| 17166 | 598 | fun no_binding args = map (pair ("", [])) args;
 | 
| 17112 | 599 | |
| 600 | local | |
| 601 | ||
| 17359 | 602 | fun gen_thmss note_ctxt more_facts opt_chain opt_result prep_atts args state = | 
| 17112 | 603 | state | 
| 604 | |> assert_forward | |
| 605 | |> map_context_result (note_ctxt (Attrib.map_facts (prep_atts (theory_of state)) args)) | |
| 606 | |> these_factss (more_facts state) | |
| 17359 | 607 | ||> opt_chain | 
| 608 | |> opt_result; | |
| 17112 | 609 | |
| 610 | in | |
| 611 | ||
| 18728 | 612 | val note_thmss = gen_thmss ProofContext.note_thmss (K []) I #2 Attrib.attribute; | 
| 17359 | 613 | val note_thmss_i = gen_thmss ProofContext.note_thmss_i (K []) I #2 (K I); | 
| 17112 | 614 | |
| 615 | val from_thmss = | |
| 18728 | 616 | gen_thmss ProofContext.note_thmss (K []) chain #2 Attrib.attribute o no_binding; | 
| 17359 | 617 | val from_thmss_i = gen_thmss ProofContext.note_thmss_i (K []) chain #2 (K I) o no_binding; | 
| 17112 | 618 | |
| 619 | val with_thmss = | |
| 18728 | 620 | gen_thmss ProofContext.note_thmss the_facts chain #2 Attrib.attribute o no_binding; | 
| 17359 | 621 | val with_thmss_i = gen_thmss ProofContext.note_thmss_i the_facts chain #2 (K I) o no_binding; | 
| 622 | ||
| 18808 | 623 | val local_results = | 
| 624 | gen_thmss ProofContext.note_thmss_i (K []) I I (K I) o map (apsnd Thm.simple_fact); | |
| 625 | fun global_results kind = PureThy.note_thmss_i kind o map (apsnd Thm.simple_fact); | |
| 17359 | 626 | |
| 627 | fun get_thmss state srcs = the_facts (note_thmss [(("", []), srcs)] state);
 | |
| 628 | fun simple_note_thms name thms = note_thmss_i [((name, []), [(thms, [])])]; | |
| 17112 | 629 | |
| 630 | end; | |
| 631 | ||
| 632 | ||
| 18548 | 633 | (* using/unfolding *) | 
| 17112 | 634 | |
| 635 | local | |
| 636 | ||
| 18548 | 637 | fun gen_using f g note prep_atts args state = | 
| 17112 | 638 | state | 
| 639 | |> assert_backward | |
| 17166 | 640 | |> map_context_result (note (Attrib.map_facts (prep_atts (theory_of state)) (no_binding args))) | 
| 18843 | 641 | |> (fn (named_facts, state') => | 
| 642 | state' |> map_goal I (fn (statement, using, goal, before_qed, after_qed) => | |
| 643 | let | |
| 644 | val ctxt = context_of state'; | |
| 645 | val ths = List.concat (map snd named_facts); | |
| 646 | in (statement, f ctxt ths using, g ctxt ths goal, before_qed, after_qed) end)); | |
| 18548 | 647 | |
| 18843 | 648 | fun append_using _ ths using = using @ ths; | 
| 18878 | 649 | fun unfold_using ctxt ths = map (LocalDefs.unfold ctxt ths); | 
| 650 | val unfold_goals = LocalDefs.unfold_goals; | |
| 17112 | 651 | |
| 652 | in | |
| 653 | ||
| 18843 | 654 | val using = gen_using append_using (K (K I)) ProofContext.note_thmss Attrib.attribute; | 
| 655 | val using_i = gen_using append_using (K (K I)) ProofContext.note_thmss_i (K I); | |
| 18826 | 656 | val unfolding = gen_using unfold_using unfold_goals ProofContext.note_thmss Attrib.attribute; | 
| 657 | val unfolding_i = gen_using unfold_using unfold_goals ProofContext.note_thmss_i (K I); | |
| 17112 | 658 | |
| 659 | end; | |
| 660 | ||
| 661 | ||
| 662 | (* case *) | |
| 663 | ||
| 664 | local | |
| 665 | ||
| 666 | fun gen_invoke_case prep_att (name, xs, raw_atts) state = | |
| 667 | let | |
| 668 | val atts = map (prep_att (theory_of state)) raw_atts; | |
| 19078 | 669 | val (asms, state') = state |> map_context_result (fn ctxt => | 
| 670 | ctxt |> ProofContext.apply_case (ProofContext.get_case ctxt name xs)); | |
| 18607 | 671 | val assumptions = asms |> map (fn (a, ts) => ((a, atts), map (rpair ([], [])) ts)); | 
| 17112 | 672 | in | 
| 673 | state' | |
| 17359 | 674 | |> map_context (ProofContext.qualified_names #> ProofContext.no_base_names) | 
| 17112 | 675 | |> assume_i assumptions | 
| 17976 | 676 | |> add_binds_i AutoBind.no_facts | 
| 17112 | 677 | |> map_context (ProofContext.restore_naming (context_of state)) | 
| 678 | |> `the_facts |-> simple_note_thms name | |
| 679 | end; | |
| 680 | ||
| 681 | in | |
| 682 | ||
| 18728 | 683 | val invoke_case = gen_invoke_case Attrib.attribute; | 
| 17112 | 684 | val invoke_case_i = gen_invoke_case (K I); | 
| 685 | ||
| 686 | end; | |
| 687 | ||
| 688 | ||
| 689 | ||
| 17359 | 690 | (** proof structure **) | 
| 691 | ||
| 692 | (* blocks *) | |
| 693 | ||
| 694 | val begin_block = | |
| 695 | assert_forward | |
| 696 | #> open_block | |
| 697 | #> put_goal NONE | |
| 698 | #> open_block; | |
| 699 | ||
| 700 | val next_block = | |
| 701 | assert_forward | |
| 702 | #> close_block | |
| 703 | #> open_block | |
| 704 | #> put_goal NONE | |
| 705 | #> put_facts NONE; | |
| 706 | ||
| 707 | fun end_block state = | |
| 708 | state | |
| 709 | |> assert_forward | |
| 710 | |> close_block | |
| 711 | |> assert_current_goal false | |
| 712 | |> close_block | |
| 713 | |> export_facts state; | |
| 714 | ||
| 715 | ||
| 716 | (* sub-proofs *) | |
| 717 | ||
| 718 | fun proof opt_text = | |
| 719 | assert_backward | |
| 17859 | 720 | #> refine (the_default Method.default_text opt_text) | 
| 17359 | 721 | #> Seq.map (using_facts [] #> enter_forward); | 
| 722 | ||
| 723 | fun end_proof bot txt = | |
| 724 | assert_forward | |
| 725 | #> assert_bottom bot | |
| 726 | #> close_block | |
| 727 | #> assert_current_goal true | |
| 728 | #> using_facts [] | |
| 17859 | 729 | #> `before_qed #-> (refine o the_default Method.succeed_text) | 
| 730 | #> Seq.maps (refine (Method.finish_text txt)); | |
| 17359 | 731 | |
| 732 | ||
| 733 | (* unstructured refinement *) | |
| 734 | ||
| 735 | fun defer i = assert_no_chain #> refine (Method.Basic (K (Method.defer i))); | |
| 736 | fun prefer i = assert_no_chain #> refine (Method.Basic (K (Method.prefer i))); | |
| 737 | ||
| 738 | fun apply text = assert_backward #> refine text #> Seq.map (using_facts []); | |
| 739 | fun apply_end text = assert_forward #> refine_end text; | |
| 740 | ||
| 741 | ||
| 742 | ||
| 17112 | 743 | (** goals **) | 
| 744 | ||
| 17359 | 745 | (* goal names *) | 
| 746 | ||
| 747 | fun prep_names prep_att stmt = | |
| 748 | let | |
| 749 | val (names_attss, propp) = split_list (Attrib.map_specs prep_att stmt); | |
| 750 | val (names, attss) = split_list names_attss; | |
| 751 | in ((names, attss), propp) end; | |
| 5820 | 752 | |
| 17359 | 753 | fun goal_names target name names = | 
| 17450 | 754 | (case target of NONE => "" | SOME "" => "" | SOME loc => " (in " ^ loc ^ ")") ^ | 
| 17359 | 755 | (if name = "" then "" else " " ^ name) ^ | 
| 756 | (case filter_out (equal "") names of [] => "" | |
| 757 |   | nms => " " ^ enclose "(" ")" (space_implode " and " (Library.take (7, nms) @
 | |
| 758 | (if length nms > 7 then ["..."] else [])))); | |
| 759 | ||
| 16813 | 760 | |
| 17359 | 761 | (* generic goals *) | 
| 762 | ||
| 763 | fun check_tvars props state = | |
| 764 | (case fold Term.add_tvars props [] of [] => () | |
| 18678 | 765 |   | tvars => error ("Goal statement contains illegal schematic type variable(s): " ^
 | 
| 766 | commas (map (ProofContext.string_of_typ (context_of state) o TVar) tvars))); | |
| 8991 | 767 | |
| 17359 | 768 | fun check_vars props state = | 
| 769 | (case fold Term.add_vars props [] of [] => () | |
| 770 |   | vars => warning ("Goal statement contains unbound schematic variable(s): " ^
 | |
| 771 | commas (map (ProofContext.string_of_term (context_of state) o Var) vars))); | |
| 772 | ||
| 17859 | 773 | fun generic_goal prepp kind before_qed after_qed raw_propp state = | 
| 5820 | 774 | let | 
| 17359 | 775 | val thy = theory_of state; | 
| 776 | val chaining = can assert_chain state; | |
| 777 | ||
| 778 | val ((propss, after_ctxt), goal_state) = | |
| 5936 | 779 | state | 
| 780 | |> assert_forward_or_chain | |
| 781 | |> enter_forward | |
| 17359 | 782 | |> open_block | 
| 17859 | 783 | |> map_context_result (fn ctxt => swap (prepp (ctxt, raw_propp))); | 
| 18503 
841137f20307
goal/qed: proper treatment of two levels of conjunctions;
 wenzelm parents: 
18475diff
changeset | 784 | val props = List.concat propss; | 
| 15703 | 785 | |
| 18503 
841137f20307
goal/qed: proper treatment of two levels of conjunctions;
 wenzelm parents: 
18475diff
changeset | 786 | val goal = Goal.init (Thm.cterm_of thy (Logic.mk_conjunction_list2 propss)); | 
| 18124 | 787 | val after_qed' = after_qed |>> (fn after_local => | 
| 788 | fn results => map_context after_ctxt #> after_local results); | |
| 5820 | 789 | in | 
| 17359 | 790 | goal_state | 
| 791 | |> tap (check_tvars props) | |
| 792 | |> tap (check_vars props) | |
| 18670 | 793 | |> map_context (ProofContext.set_body true) | 
| 17859 | 794 | |> put_goal (SOME (make_goal ((kind, propss), [], goal, before_qed, after_qed'))) | 
| 18475 | 795 | |> map_context (ProofContext.add_cases false (AutoBind.cases thy props)) | 
| 17359 | 796 | |> map_context (ProofContext.auto_bind_goal props) | 
| 797 | |> K chaining ? (`the_facts #-> using_facts) | |
| 798 | |> put_facts NONE | |
| 799 | |> open_block | |
| 800 | |> put_goal NONE | |
| 5820 | 801 | |> enter_backward | 
| 17450 | 802 | |> K (null props) ? (refine (Method.Basic Method.assumption) #> Seq.hd) | 
| 5820 | 803 | end; | 
| 804 | ||
| 17359 | 805 | fun generic_qed state = | 
| 12503 | 806 | let | 
| 18548 | 807 |     val (goal_ctxt, {statement = (_, stmt), using = _, goal, before_qed = _, after_qed}) =
 | 
| 17859 | 808 | current_goal state; | 
| 8617 
33e2bd53aec3
support Hindley-Milner polymorphisms in binds and facts;
 wenzelm parents: 
8582diff
changeset | 809 | val outer_state = state |> close_block; | 
| 
33e2bd53aec3
support Hindley-Milner polymorphisms in binds and facts;
 wenzelm parents: 
8582diff
changeset | 810 | val outer_ctxt = context_of outer_state; | 
| 
33e2bd53aec3
support Hindley-Milner polymorphisms in binds and facts;
 wenzelm parents: 
8582diff
changeset | 811 | |
| 18503 
841137f20307
goal/qed: proper treatment of two levels of conjunctions;
 wenzelm parents: 
18475diff
changeset | 812 | val props = | 
| 
841137f20307
goal/qed: proper treatment of two levels of conjunctions;
 wenzelm parents: 
18475diff
changeset | 813 | List.concat stmt | 
| 
841137f20307
goal/qed: proper treatment of two levels of conjunctions;
 wenzelm parents: 
18475diff
changeset | 814 | |> ProofContext.generalize goal_ctxt outer_ctxt; | 
| 17359 | 815 | val results = | 
| 18450 
e57731ba01dd
discontinued unflat in favour of burrow and burrow_split
 haftmann parents: 
18377diff
changeset | 816 | stmt | 
| 18503 
841137f20307
goal/qed: proper treatment of two levels of conjunctions;
 wenzelm parents: 
18475diff
changeset | 817 | |> conclude_goal state goal | 
| 18450 
e57731ba01dd
discontinued unflat in favour of burrow and burrow_split
 haftmann parents: 
18377diff
changeset | 818 | |> (Seq.map_list o Seq.map_list) (ProofContext.exports goal_ctxt outer_ctxt); | 
| 17359 | 819 | in | 
| 820 | outer_state | |
| 821 | |> map_context (ProofContext.auto_bind_facts props) | |
| 18124 | 822 | |> pair (after_qed, results) | 
| 17359 | 823 | end; | 
| 824 | ||
| 9469 | 825 | |
| 17359 | 826 | (* local goals *) | 
| 827 | ||
| 17859 | 828 | fun local_goal print_results prep_att prepp kind before_qed after_qed stmt state = | 
| 17359 | 829 | let | 
| 830 | val ((names, attss), propp) = prep_names (prep_att (theory_of state)) stmt; | |
| 831 | ||
| 18124 | 832 | fun after_qed' results = | 
| 18808 | 833 | local_results ((names ~~ attss) ~~ results) | 
| 17359 | 834 | #-> (fn res => tap (fn st => print_results (context_of st) ((kind, ""), res) : unit)) | 
| 18124 | 835 | #> after_qed results; | 
| 5820 | 836 | in | 
| 17359 | 837 | state | 
| 18124 | 838 | |> generic_goal prepp (kind ^ goal_names NONE "" names) before_qed (after_qed', K I) propp | 
| 17359 | 839 | |> warn_extra_tfrees state | 
| 5820 | 840 | end; | 
| 841 | ||
| 17359 | 842 | fun local_qed txt = | 
| 843 | end_proof false txt | |
| 844 | #> Seq.map generic_qed | |
| 18124 | 845 | #> Seq.maps (uncurry (fn ((after_qed, _), results) => Seq.lifts after_qed results)); | 
| 5820 | 846 | |
| 847 | ||
| 17359 | 848 | (* global goals *) | 
| 849 | ||
| 850 | fun global_goal print_results prep_att prepp | |
| 17859 | 851 | kind before_qed after_qed target (name, raw_atts) stmt ctxt = | 
| 17359 | 852 | let | 
| 853 | val thy = ProofContext.theory_of ctxt; | |
| 854 | val thy_ctxt = ProofContext.init thy; | |
| 855 | ||
| 856 | val atts = map (prep_att thy) raw_atts; | |
| 857 | val ((names, attss), propp) = prep_names (prep_att thy) stmt; | |
| 858 | ||
| 17450 | 859 | fun store_results prfx res = | 
| 860 | K (prfx <> "") ? (Sign.add_path prfx #> Sign.no_base_names) | |
| 861 | #> global_results kind ((names ~~ attss) ~~ res) | |
| 17359 | 862 | #-> (fn res' => | 
| 863 | (print_results thy_ctxt ((kind, name), res') : unit; | |
| 864 | #2 o global_results kind [((name, atts), List.concat (map #2 res'))])) | |
| 17450 | 865 | #> Sign.restore_naming thy; | 
| 17359 | 866 | |
| 18124 | 867 | fun after_qed' results = | 
| 17450 | 868 | (case target of NONE => I | 
| 869 | | SOME prfx => store_results (NameSpace.base prfx) | |
| 18784 | 870 | (map (map (ProofContext.export_standard ctxt thy_ctxt | 
| 17450 | 871 | #> Drule.strip_shyps_warning)) results)) | 
| 18124 | 872 | #> after_qed results; | 
| 17359 | 873 | in | 
| 874 | init ctxt | |
| 18670 | 875 | |> generic_goal (prepp #> ProofContext.auto_fixes) (kind ^ goal_names target name names) | 
| 18124 | 876 | before_qed (K Seq.single, after_qed') propp | 
| 17359 | 877 | end; | 
| 12065 | 878 | |
| 18678 | 879 | fun check_result msg sq = | 
| 17112 | 880 | (case Seq.pull sq of | 
| 18678 | 881 | NONE => error msg | 
| 17112 | 882 | | SOME res => Seq.cons res); | 
| 883 | ||
| 17359 | 884 | fun global_qeds txt = | 
| 885 | end_proof true txt | |
| 886 | #> Seq.map generic_qed | |
| 18124 | 887 | #> Seq.maps (fn (((_, after_qed), results), state) => | 
| 888 | Seq.lift after_qed results (theory_of state) | |
| 19100 | 889 | |> Seq.map (fn thy => (ProofContext.transfer thy (context_of state), thy))) | 
| 17112 | 890 | |> Seq.DETERM; (*backtracking may destroy theory!*) | 
| 891 | ||
| 18678 | 892 | fun global_qed txt = | 
| 893 | global_qeds txt | |
| 894 | #> check_result "Failed to finish proof" | |
| 895 | #> Seq.hd; | |
| 12959 | 896 | |
| 5820 | 897 | |
| 17359 | 898 | (* concluding steps *) | 
| 17112 | 899 | |
| 17359 | 900 | fun local_terminal_proof (text, opt_text) = | 
| 901 | proof (SOME text) #> Seq.maps (local_qed (opt_text, true)); | |
| 17112 | 902 | |
| 903 | val local_default_proof = local_terminal_proof (Method.default_text, NONE); | |
| 904 | val local_immediate_proof = local_terminal_proof (Method.this_text, NONE); | |
| 17359 | 905 | val local_done_proof = proof (SOME Method.done_text) #> Seq.maps (local_qed (NONE, false)); | 
| 906 | fun local_skip_proof int = local_terminal_proof (Method.sorry_text int, NONE); | |
| 17112 | 907 | |
| 18678 | 908 | fun global_term_proof immed (text, opt_text) = | 
| 909 | proof (SOME text) | |
| 910 | #> check_result "Terminal proof method failed" | |
| 911 | #> Seq.maps (global_qeds (opt_text, immed)) | |
| 912 | #> check_result "Failed to finish proof (after successful terminal method)" | |
| 913 | #> Seq.hd; | |
| 17112 | 914 | |
| 915 | val global_terminal_proof = global_term_proof true; | |
| 916 | val global_default_proof = global_terminal_proof (Method.default_text, NONE); | |
| 917 | val global_immediate_proof = global_terminal_proof (Method.this_text, NONE); | |
| 918 | val global_done_proof = global_term_proof false (Method.done_text, NONE); | |
| 17359 | 919 | fun global_skip_proof int = global_terminal_proof (Method.sorry_text int, NONE); | 
| 5820 | 920 | |
| 6896 | 921 | |
| 17359 | 922 | (* common goal statements *) | 
| 923 | ||
| 924 | local | |
| 925 | ||
| 17859 | 926 | fun gen_have prep_att prepp before_qed after_qed stmt int = | 
| 927 | local_goal (ProofDisplay.print_results int) prep_att prepp "have" before_qed after_qed stmt; | |
| 6896 | 928 | |
| 17859 | 929 | fun gen_show prep_att prepp before_qed after_qed stmt int state = | 
| 17359 | 930 | let | 
| 931 | val testing = ref false; | |
| 932 | val rule = ref (NONE: thm option); | |
| 933 | fun fail_msg ctxt = | |
| 934 | "Local statement will fail to solve any pending goal" :: | |
| 935 | (case ! rule of NONE => [] | SOME th => [ProofDisplay.string_of_rule ctxt "Failed" th]) | |
| 936 | |> cat_lines; | |
| 6896 | 937 | |
| 17359 | 938 | fun print_results ctxt res = | 
| 939 | if ! testing then () else ProofDisplay.print_results int ctxt res; | |
| 940 | fun print_rule ctxt th = | |
| 941 | if ! testing then rule := SOME th | |
| 942 | else if int then priority (ProofDisplay.string_of_rule ctxt "Successful" th) | |
| 943 | else (); | |
| 944 | val test_proof = | |
| 945 | (Seq.pull oo local_skip_proof) true | |
| 946 | |> setmp testing true | |
| 947 | |> setmp proofs 0 | |
| 948 | |> capture; | |
| 6896 | 949 | |
| 18124 | 950 | fun after_qed' results = | 
| 17359 | 951 | refine_goals print_rule (context_of state) (List.concat results) | 
| 18124 | 952 | #> Seq.maps (after_qed results); | 
| 17359 | 953 | in | 
| 954 | state | |
| 17859 | 955 | |> local_goal print_results prep_att prepp "show" before_qed after_qed' stmt | 
| 17359 | 956 | |> K int ? (fn goal_state => | 
| 957 | (case test_proof goal_state of | |
| 958 | Result (SOME _) => goal_state | |
| 18678 | 959 | | Result NONE => error (fail_msg (context_of goal_state)) | 
| 17359 | 960 | | Exn Interrupt => raise Interrupt | 
| 961 | | Exn exn => raise EXCEPTION (exn, fail_msg (context_of goal_state)))) | |
| 962 | end; | |
| 963 | ||
| 17859 | 964 | fun gen_theorem prep_att prepp kind before_qed after_qed target a = | 
| 965 | global_goal ProofDisplay.present_results prep_att prepp kind before_qed after_qed target a; | |
| 17359 | 966 | |
| 967 | in | |
| 968 | ||
| 18728 | 969 | val have = gen_have Attrib.attribute ProofContext.bind_propp; | 
| 17359 | 970 | val have_i = gen_have (K I) ProofContext.bind_propp_i; | 
| 18728 | 971 | val show = gen_show Attrib.attribute ProofContext.bind_propp; | 
| 17359 | 972 | val show_i = gen_show (K I) ProofContext.bind_propp_i; | 
| 18728 | 973 | val theorem = gen_theorem Attrib.attribute ProofContext.bind_propp_schematic; | 
| 17359 | 974 | val theorem_i = gen_theorem (K I) ProofContext.bind_propp_schematic_i; | 
| 6896 | 975 | |
| 5820 | 976 | end; | 
| 17359 | 977 | |
| 978 | end; |