121 fun steps_of_isar_proof (Proof (_, _, steps)) = steps |
121 fun steps_of_isar_proof (Proof (_, _, steps)) = steps |
122 |
122 |
123 fun label_of_isar_step (Prove (_, _, l, _, _, _, _)) = SOME l |
123 fun label_of_isar_step (Prove (_, _, l, _, _, _, _)) = SOME l |
124 | label_of_isar_step _ = NONE |
124 | label_of_isar_step _ = NONE |
125 |
125 |
126 fun subproofs_of_isar_step (Prove (_, _, _, _, subproofs, _, _)) = SOME subproofs |
126 fun subproofs_of_isar_step (Prove (_, _, _, _, subs, _, _)) = subs |
127 | subproofs_of_isar_step _ = NONE |
127 | subproofs_of_isar_step _ = [] |
128 |
128 |
129 fun facts_of_isar_step (Prove (_, _, _, _, _, facts, _)) = facts |
129 fun facts_of_isar_step (Prove (_, _, _, _, _, facts, _)) = facts |
130 | facts_of_isar_step _ = ([], []) |
130 | facts_of_isar_step _ = ([], []) |
131 |
131 |
132 fun proof_methods_of_isar_step (Prove (_, _, _, _, _, _, meths)) = meths |
132 fun proof_methods_of_isar_step (Prove (_, _, _, _, _, _, meths)) = meths |
133 | proof_methods_of_isar_step _ = [] |
133 | proof_methods_of_isar_step _ = [] |
134 |
134 |
135 fun fold_isar_step f step = |
135 fun fold_isar_step f step = |
136 fold (steps_of_isar_proof #> fold_isar_steps f) (these (subproofs_of_isar_step step)) #> f step |
136 fold (steps_of_isar_proof #> fold_isar_steps f) (subproofs_of_isar_step step) #> f step |
137 and fold_isar_steps f = fold (fold_isar_step f) |
137 and fold_isar_steps f = fold (fold_isar_step f) |
138 |
138 |
139 fun map_isar_steps f = |
139 fun map_isar_steps f = |
140 let |
140 let |
141 fun map_proof (Proof (fix, assms, steps)) = Proof (fix, assms, map map_step steps) |
141 fun map_proof (Proof (fix, assms, steps)) = Proof (fix, assms, map map_step steps) |
142 and map_step (step as Let _) = f step |
142 and map_step (step as Let _) = f step |
143 | map_step (Prove (qs, xs, l, t, subproofs, facts, meths)) = |
143 | map_step (Prove (qs, xs, l, t, subs, facts, meths)) = |
144 f (Prove (qs, xs, l, t, map map_proof subproofs, facts, meths)) |
144 f (Prove (qs, xs, l, t, map map_proof subs, facts, meths)) |
145 in map_proof end |
145 in map_proof end |
146 |
146 |
147 val add_isar_steps = fold_isar_steps (fn Prove _ => Integer.add 1 | _ => I) |
147 val add_isar_steps = fold_isar_steps (fn Prove _ => Integer.add 1 | _ => I) |
148 |
148 |
149 (* canonical proof labels: 1, 2, 3, ... in post traversal order *) |
149 (* canonical proof labels: 1, 2, 3, ... in post traversal order *) |
154 val ord = canonical_label_ord) |
154 val ord = canonical_label_ord) |
155 |
155 |
156 fun chain_qs_lfs NONE lfs = ([], lfs) |
156 fun chain_qs_lfs NONE lfs = ([], lfs) |
157 | chain_qs_lfs (SOME l0) lfs = |
157 | chain_qs_lfs (SOME l0) lfs = |
158 if member (op =) lfs l0 then ([Then], lfs |> remove (op =) l0) else ([], lfs) |
158 if member (op =) lfs l0 then ([Then], lfs |> remove (op =) l0) else ([], lfs) |
159 fun chain_isar_step lbl (Prove (qs, xs, l, t, subproofs, (lfs, gfs), meths)) = |
159 fun chain_isar_step lbl (Prove (qs, xs, l, t, subs, (lfs, gfs), meths)) = |
160 let val (qs', lfs) = chain_qs_lfs lbl lfs in |
160 let val (qs', lfs) = chain_qs_lfs lbl lfs in |
161 Prove (qs' @ qs, xs, l, t, map chain_isar_proof subproofs, (lfs, gfs), meths) |
161 Prove (qs' @ qs, xs, l, t, map chain_isar_proof subs, (lfs, gfs), meths) |
162 end |
162 end |
163 | chain_isar_step _ step = step |
163 | chain_isar_step _ step = step |
164 and chain_isar_steps _ [] = [] |
164 and chain_isar_steps _ [] = [] |
165 | chain_isar_steps (prev as SOME _) (i :: is) = |
165 | chain_isar_steps (prev as SOME _) (i :: is) = |
166 chain_isar_step prev i :: chain_isar_steps (label_of_isar_step i) is |
166 chain_isar_step prev i :: chain_isar_steps (label_of_isar_step i) is |
173 val used_ls = |
173 val used_ls = |
174 fold_isar_steps (facts_of_isar_step #> fst #> union (op =)) (steps_of_isar_proof proof) [] |
174 fold_isar_steps (facts_of_isar_step #> fst #> union (op =)) (steps_of_isar_proof proof) [] |
175 |
175 |
176 fun kill_label l = if member (op =) used_ls l then l else no_label |
176 fun kill_label l = if member (op =) used_ls l then l else no_label |
177 |
177 |
178 fun kill_step (Prove (qs, xs, l, t, subproofs, facts, meths)) = |
178 fun kill_step (Prove (qs, xs, l, t, subs, facts, meths)) = |
179 Prove (qs, xs, kill_label l, t, map kill_proof subproofs, facts, meths) |
179 Prove (qs, xs, kill_label l, t, map kill_proof subs, facts, meths) |
180 | kill_step step = step |
180 | kill_step step = step |
181 and kill_proof (Proof (fix, assms, steps)) = |
181 and kill_proof (Proof (fix, assms, steps)) = |
182 Proof (fix, map (apfst kill_label) assms, map kill_step steps) |
182 Proof (fix, map (apfst kill_label) assms, map kill_step steps) |
183 in |
183 in |
184 kill_proof proof |
184 kill_proof proof |
187 fun relabel_isar_proof_canonically proof = |
187 fun relabel_isar_proof_canonically proof = |
188 let |
188 let |
189 fun next_label l (next, subst) = |
189 fun next_label l (next, subst) = |
190 let val l' = ("", next) in (l', (next + 1, (l, l') :: subst)) end |
190 let val l' = ("", next) in (l', (next + 1, (l, l') :: subst)) end |
191 |
191 |
192 fun relabel_facts (lfs, gfs) (_, subst) = |
192 fun relabel_step (Prove (qs, fix, l, t, subs, (lfs, gfs), meths)) (accum as (_, subst)) = |
193 (map (AList.lookup (op =) subst #> the) lfs, gfs) |
|
194 handle Option.Option => |
|
195 raise Fail "Sledgehammer_Isar_Proof: relabel_isar_proof_canonically" |
|
196 |
|
197 fun relabel_assm (l, t) state = |
|
198 next_label l state |> (fn (l, state) => ((l, t), state)) |
|
199 |
|
200 fun relabel_proof (Proof (fix, assms, steps)) state = |
|
201 let |
|
202 val (assms, state) = fold_map relabel_assm assms state |
|
203 val (steps, state) = fold_map relabel_step steps state |
|
204 in |
|
205 (Proof (fix, assms, steps), state) |
|
206 end |
|
207 |
|
208 and relabel_step (Prove (qs, fix, l, t, subproofs, facts, meths)) state = |
|
209 let |
193 let |
210 val facts = relabel_facts facts state |
194 val lfs' = maps (the_list o AList.lookup (op =) subst) lfs |
211 val (subproofs, state) = fold_map relabel_proof subproofs state |
195 val ((subs', l'), accum') = accum |
212 val (l, state) = next_label l state |
196 |> fold_map relabel_proof subs |
|
197 ||>> next_label l |
213 in |
198 in |
214 (Prove (qs, fix, l, t, subproofs, facts, meths), state) |
199 (Prove (qs, fix, l', t, subs', (lfs', gfs), meths), accum') |
215 end |
200 end |
216 | relabel_step step state = (step, state) |
201 | relabel_step step accum = (step, accum) |
|
202 and relabel_proof (Proof (fix, assms, steps)) = |
|
203 fold_map (fn (l, t) => next_label l #> apfst (rpair t)) assms |
|
204 ##>> fold_map relabel_step steps |
|
205 #>> (fn (assms, steps) => Proof (fix, assms, steps)) |
217 in |
206 in |
218 fst (relabel_proof proof (0, [])) |
207 fst (relabel_proof proof (0, [])) |
219 end |
208 end |
220 |
209 |
221 val assume_prefix = "a" |
210 val assume_prefix = "a" |
222 val have_prefix = "f" |
211 val have_prefix = "f" |
223 |
212 |
224 val relabel_isar_proof_finally = |
213 val relabel_isar_proof_finally = |
225 let |
214 let |
226 fun fresh_label depth prefix (accum as (l, subst, next)) = |
215 fun next_label depth prefix l (accum as (next, subst)) = |
227 if l = no_label then |
216 if l = no_label then |
228 accum |
217 (l, accum) |
229 else |
218 else |
230 let val l' = (replicate_string (depth + 1) prefix, next) in |
219 let val l' = (replicate_string (depth + 1) prefix, next) in |
231 (l', (l, l') :: subst, next + 1) |
220 (l', (next + 1, (l, l') :: subst)) |
232 end |
221 end |
233 |
222 |
234 fun relabel_facts subst = apfst (maps (the_list o AList.lookup (op =) subst)) |
223 fun relabel_step depth (Prove (qs, xs, l, t, subs, (lfs, gfs), meths)) (accum as (_, subst)) = |
235 |
|
236 fun relabel_assm depth (l, t) (subst, next) = |
|
237 let val (l, subst, next) = (l, subst, next) |> fresh_label depth assume_prefix in |
|
238 ((l, t), (subst, next)) |
|
239 end |
|
240 |
|
241 fun relabel_assms subst depth assms = fold_map (relabel_assm depth) assms (subst, 1) ||> fst |
|
242 |
|
243 fun relabel_steps _ _ _ [] = [] |
|
244 | relabel_steps subst depth next (Prove (qs, xs, l, t, sub, facts, meths) :: steps) = |
|
245 let |
224 let |
246 val (l, subst, next) = (l, subst, next) |> fresh_label depth have_prefix |
225 val lfs' = maps (the_list o AList.lookup (op =) subst) lfs |
247 val sub = relabel_proofs subst depth sub |
226 val (l', accum' as (next', subst')) = next_label depth have_prefix l accum |
248 val facts = relabel_facts subst facts |
227 val subs' = map (relabel_proof subst' (depth + 1)) subs |
249 in |
228 in |
250 Prove (qs, xs, l, t, sub, facts, meths) :: relabel_steps subst depth next steps |
229 (Prove (qs, xs, l', t, subs', (lfs', gfs), meths), accum') |
251 end |
230 end |
252 | relabel_steps subst depth next (step :: steps) = |
231 | relabel_step _ step accum = (step, accum) |
253 step :: relabel_steps subst depth next steps |
|
254 and relabel_proof subst depth (Proof (fix, assms, steps)) = |
232 and relabel_proof subst depth (Proof (fix, assms, steps)) = |
255 let val (assms, subst) = relabel_assms subst depth assms in |
233 (1, subst) |
256 Proof (fix, assms, relabel_steps subst depth 1 steps) |
234 |> fold_map (fn (l, t) => next_label depth assume_prefix l #> apfst (rpair t)) assms |
257 end |
235 ||>> fold_map (relabel_step depth) steps |
258 and relabel_proofs subst depth = map (relabel_proof subst (depth + 1)) |
236 |> (fn ((assms, steps), _) => Proof (fix, assms, steps)) |
259 in |
237 in |
260 relabel_proof [] 0 |
238 relabel_proof [] 0 |
261 end |
239 end |
262 |
240 |
263 val indent_size = 2 |
241 val indent_size = 2 |
318 (* Local facts are always passed via "using", which affects "meson" and "metis". This is |
296 (* Local facts are always passed via "using", which affects "meson" and "metis". This is |
319 arguably stylistically superior, because it emphasises the structure of the proof. It is also |
297 arguably stylistically superior, because it emphasises the structure of the proof. It is also |
320 more robust w.r.t. preplay: Preplay is performed before chaining of local facts with "hence" |
298 more robust w.r.t. preplay: Preplay is performed before chaining of local facts with "hence" |
321 and "thus" is introduced. See also "tac_of_method" in "Sledgehammer_Isar_Preplay". *) |
299 and "thus" is introduced. See also "tac_of_method" in "Sledgehammer_Isar_Preplay". *) |
322 fun of_method ls ss meth = |
300 fun of_method ls ss meth = |
323 let val direct = is_direct_method meth in |
301 let val direct = is_direct_method meth in |
324 using_facts ls (if direct then [] else ss) ^ |
302 using_facts ls (if direct then [] else ss) ^ |
325 by_facts (string_of_proof_method meth) [] (if direct then ss else []) |
303 by_facts (string_of_proof_method meth) [] (if direct then ss else []) |
326 end |
304 end |
327 |
305 |
328 fun of_free (s, T) = |
306 fun of_free (s, T) = |
329 maybe_quote s ^ " :: " ^ |
307 maybe_quote s ^ " :: " ^ |
330 maybe_quote (simplify_spaces (with_vanilla_print_mode (Syntax.string_of_typ ctxt) T)) |
308 maybe_quote (simplify_spaces (with_vanilla_print_mode (Syntax.string_of_typ ctxt) T)) |
331 |
309 |
332 fun add_frees xs (s, ctxt) = |
310 fun add_frees xs (s, ctxt) = |
333 (s ^ space_implode " and " (map of_free xs), ctxt |> register_fixes xs) |
311 (s ^ space_implode " and " (map of_free xs), ctxt |> register_fixes xs) |
334 |
312 |
335 fun add_fix _ [] = I |
313 fun add_fix _ [] = I |
336 | add_fix ind xs = |
314 | add_fix ind xs = add_str (of_indent ind ^ "fix ") #> add_frees xs #> add_str "\n" |
337 add_str (of_indent ind ^ "fix ") |
|
338 #> add_frees xs |
|
339 #> add_str "\n" |
|
340 |
315 |
341 fun add_assm ind (l, t) = |
316 fun add_assm ind (l, t) = |
342 add_str (of_indent ind ^ "assume " ^ of_label l) |
317 add_str (of_indent ind ^ "assume " ^ of_label l) #> add_term t #> add_str "\n" |
343 #> add_term t |
|
344 #> add_str "\n" |
|
345 |
|
346 fun add_assms ind assms = fold (add_assm ind) assms |
|
347 |
318 |
348 fun of_subproof ind ctxt proof = |
319 fun of_subproof ind ctxt proof = |
349 let |
320 let |
350 val ind = ind + 1 |
321 val ind = ind + 1 |
351 val s = of_proof ind ctxt proof |
322 val s = of_proof ind ctxt proof |
355 replicate_string (ind * indent_size - size prefix) " " ^ prefix ^ |
326 replicate_string (ind * indent_size - size prefix) " " ^ prefix ^ |
356 String.extract (s, ind * indent_size, SOME (size s - ind * indent_size - 1)) ^ |
327 String.extract (s, ind * indent_size, SOME (size s - ind * indent_size - 1)) ^ |
357 suffix ^ "\n" |
328 suffix ^ "\n" |
358 end |
329 end |
359 and of_subproofs _ _ _ [] = "" |
330 and of_subproofs _ _ _ [] = "" |
360 | of_subproofs ind ctxt qs subproofs = |
331 | of_subproofs ind ctxt qs subs = |
361 (if member (op =) qs Then then of_moreover ind else "") ^ |
332 (if member (op =) qs Then then of_moreover ind else "") ^ |
362 space_implode (of_moreover ind) (map (of_subproof ind ctxt) subproofs) |
333 space_implode (of_moreover ind) (map (of_subproof ind ctxt) subs) |
363 and add_step_pre ind qs subproofs (s, ctxt) = |
334 and add_step_pre ind qs subs (s, ctxt) = |
364 (s ^ of_subproofs ind ctxt qs subproofs ^ of_indent ind, ctxt) |
335 (s ^ of_subproofs ind ctxt qs subs ^ of_indent ind, ctxt) |
365 and add_step ind (Let (t1, t2)) = |
336 and add_step ind (Let (t1, t2)) = |
366 add_str (of_indent ind ^ "let ") |
337 add_str (of_indent ind ^ "let ") |
367 #> add_term t1 #> add_str " = " #> add_term t2 |
338 #> add_term t1 #> add_str " = " #> add_term t2 #> add_str "\n" |
368 #> add_str "\n" |
339 | add_step ind (Prove (qs, xs, l, t, subs, (ls, ss), meths as meth :: _)) = |
369 | add_step ind (Prove (qs, xs, l, t, subproofs, (ls, ss), meths as meth :: _)) = |
340 add_step_pre ind qs subs |
370 add_step_pre ind qs subproofs |
|
371 #> (case xs of |
341 #> (case xs of |
372 [] => add_str (of_have qs (length subproofs) ^ " ") |
342 [] => add_str (of_have qs (length subs) ^ " ") |
373 | _ => |
343 | _ => add_str (of_obtain qs (length subs) ^ " ") #> add_frees xs #> add_str " where ") |
374 add_str (of_obtain qs (length subproofs) ^ " ") #> add_frees xs #> add_str " where ") |
|
375 #> add_str (of_label l) |
344 #> add_str (of_label l) |
376 #> add_term t |
345 #> add_term t |
377 #> add_str (" " ^ |
346 #> add_str (" " ^ |
378 of_method (sort_distinct label_ord ls) (sort_distinct string_ord ss) meth ^ |
347 of_method (sort_distinct label_ord ls) (sort_distinct string_ord ss) meth ^ |
379 (case comment_of l meths of |
348 (case comment_of l meths of |
380 "" => "" |
349 "" => "" |
381 | comment => " (* " ^ comment ^ " *)") ^ "\n") |
350 | comment => " (* " ^ comment ^ " *)") ^ "\n") |
382 and add_steps ind = fold (add_step ind) |
351 and add_steps ind = fold (add_step ind) |
383 and of_proof ind ctxt (Proof (xs, assms, steps)) = |
352 and of_proof ind ctxt (Proof (xs, assms, steps)) = |
384 ("", ctxt) |> add_fix ind xs |> add_assms ind assms |> add_steps ind steps |> fst |
353 ("", ctxt) |
|
354 |> add_fix ind xs |
|
355 |> fold (add_assm ind) assms |
|
356 |> add_steps ind steps |
|
357 |> fst |
385 in |
358 in |
386 (* One-step Metis proofs are pointless; better use the one-liner directly. *) |
359 (* One-step Metis proofs are pointless; better use the one-liner directly. *) |
387 (case proof of |
360 (case proof of |
388 Proof ([], [], []) => "" (* degenerate case: the conjecture is "True" with Z3 *) |
361 Proof ([], [], []) => "" (* degenerate case: the conjecture is "True" with Z3 *) |
389 | Proof ([], [], [Prove (_, [], _, _, [], _, Metis_Method _ :: _)]) => "" |
362 | Proof ([], [], [Prove (_, [], _, _, [], _, Metis_Method _ :: _)]) => "" |