798 else wipe_out_mash_state_dir (); |
798 else wipe_out_mash_state_dir (); |
799 (Graph.empty, 0)) |
799 (Graph.empty, 0)) |
800 | GREATER => raise FILE_VERSION_TOO_NEW ()) |
800 | GREATER => raise FILE_VERSION_TOO_NEW ()) |
801 in |
801 in |
802 trace_msg ctxt (fn () => "Loaded fact graph (" ^ graph_info access_G ^ ")"); |
802 trace_msg ctxt (fn () => "Loaded fact graph (" ^ graph_info access_G ^ ")"); |
803 {access_G = access_G, num_known_facts = num_known_facts, dirty = SOME []} |
803 {access_G = access_G, num_known_facts = num_known_facts, dirty_facts = SOME []} |
804 end |
804 end |
805 | _ => empty_state))) |
805 | _ => empty_state))) |
806 end |
806 end |
807 |
807 |
808 fun str_of_entry (kind, name, parents, feats, deps) = |
808 fun str_of_entry (kind, name, parents, feats, deps) = |
809 str_of_proof_kind kind ^ " " ^ encode_str name ^ ": " ^ encode_strs parents ^ "; " ^ |
809 str_of_proof_kind kind ^ " " ^ encode_str name ^ ": " ^ encode_strs parents ^ "; " ^ |
810 encode_strs feats ^ "; " ^ encode_strs deps ^ "\n" |
810 encode_strs feats ^ "; " ^ encode_strs deps ^ "\n" |
811 |
811 |
812 fun save_state _ (time_state as (_, {dirty = SOME [], ...})) = time_state |
812 fun save_state _ (time_state as (_, {dirty_facts = SOME [], ...})) = time_state |
813 | save_state ctxt (memory_time, {access_G, num_known_facts, dirty}) = |
813 | save_state ctxt (memory_time, {access_G, num_known_facts, dirty_facts}) = |
814 let |
814 let |
815 fun append_entry (name, ((kind, feats, deps), (parents, _))) = |
815 fun append_entry (name, ((kind, feats, deps), (parents, _))) = |
816 cons (kind, name, Graph.Keys.dest parents, feats, deps) |
816 cons (kind, name, Graph.Keys.dest parents, feats, deps) |
817 |
817 |
818 val path = mash_state_file () |
818 val path = mash_state_file () |
819 val dirty' = |
819 val dirty_facts' = |
820 (case try OS.FileSys.modTime (Path.implode path) of |
820 (case try OS.FileSys.modTime (Path.implode path) of |
821 NONE => NONE |
821 NONE => NONE |
822 | SOME disk_time => if Time.< (disk_time, memory_time) then dirty else NONE) |
822 | SOME disk_time => if Time.< (disk_time, memory_time) then dirty_facts else NONE) |
823 val (banner, entries) = |
823 val (banner, entries) = |
824 (case dirty' of |
824 (case dirty_facts' of |
825 SOME names => (NONE, fold (append_entry o Graph.get_entry access_G) names []) |
825 SOME names => (NONE, fold (append_entry o Graph.get_entry access_G) names []) |
826 | NONE => (SOME (version ^ "\n"), Graph.fold append_entry access_G [])) |
826 | NONE => (SOME (version ^ "\n"), Graph.fold append_entry access_G [])) |
827 in |
827 in |
828 write_file banner (entries, str_of_entry) path; |
828 write_file banner (entries, str_of_entry) path; |
829 trace_msg ctxt (fn () => |
829 trace_msg ctxt (fn () => |
830 "Saved fact graph (" ^ graph_info access_G ^ |
830 "Saved fact graph (" ^ graph_info access_G ^ |
831 (case dirty of |
831 (case dirty_facts of |
832 SOME dirty => "; " ^ string_of_int (length dirty) ^ " dirty fact(s)" |
832 SOME dirty_facts => "; " ^ string_of_int (length dirty_facts) ^ " dirty fact(s)" |
833 | _ => "") ^ ")"); |
833 | _ => "") ^ ")"); |
834 (Time.now (), {access_G = access_G, num_known_facts = num_known_facts, dirty = SOME []}) |
834 (Time.now (), {access_G = access_G, num_known_facts = num_known_facts, dirty_facts = SOME []}) |
835 end |
835 end |
836 |
836 |
837 val global_state = |
837 val global_state = Synchronized.var "Sledgehammer_MaSh.global_state" (Time.zeroTime, empty_state) |
838 Synchronized.var "Sledgehammer_MaSh.global_state" (Time.zeroTime, empty_state) |
|
839 |
838 |
840 in |
839 in |
841 |
840 |
842 fun map_state ctxt overlord f = |
841 fun map_state ctxt overlord f = |
843 Synchronized.change global_state (load_state ctxt overlord ##> f #> save_state ctxt) |
842 Synchronized.change global_state (load_state ctxt overlord ##> f #> save_state ctxt) |
1465 launch_thread timeout (fn () => |
1464 launch_thread timeout (fn () => |
1466 let |
1465 let |
1467 val thy = Proof_Context.theory_of ctxt |
1466 val thy = Proof_Context.theory_of ctxt |
1468 val feats = map fst (features_of ctxt thy 0 Symtab.empty (Local, General) [t]) |
1467 val feats = map fst (features_of ctxt thy 0 Symtab.empty (Local, General) [t]) |
1469 in |
1468 in |
1470 map_state ctxt overlord (fn state as {access_G, num_known_facts, dirty} => |
1469 map_state ctxt overlord (fn state as {access_G, num_known_facts, dirty_facts} => |
1471 let |
1470 let |
1472 val parents = maximal_wrt_access_graph access_G facts |
1471 val parents = maximal_wrt_access_graph access_G facts |
1473 val deps = used_ths |
1472 val deps = used_ths |
1474 |> filter (is_fact_in_graph access_G) |
1473 |> filter (is_fact_in_graph access_G) |
1475 |> map nickname_of_thm |
1474 |> map nickname_of_thm |
1527 |> (fn (false, _) => NONE | (true, deps) => trim_dependencies deps) |
1526 |> (fn (false, _) => NONE | (true, deps) => trim_dependencies deps) |
1528 else |
1527 else |
1529 isar_dependencies_of name_tabs th |
1528 isar_dependencies_of name_tabs th |
1530 |
1529 |
1531 fun do_commit [] [] [] state = state |
1530 fun do_commit [] [] [] state = state |
1532 | do_commit learns relearns flops {access_G, num_known_facts, dirty} = |
1531 | do_commit learns relearns flops {access_G, num_known_facts, dirty_facts} = |
1533 let |
1532 let |
1534 val was_empty = Graph.is_empty access_G |
1533 val was_empty = Graph.is_empty access_G |
1535 val (learns, access_G) = ([], access_G) |> fold (learn_wrt_access_graph ctxt) learns |
1534 val (learns, access_G) = ([], access_G) |> fold (learn_wrt_access_graph ctxt) learns |
1536 val (relearns, access_G) = |
1535 val (relearns, access_G) = |
1537 ([], access_G) |> fold (relearn_wrt_access_graph ctxt) relearns |
1536 ([], access_G) |> fold (relearn_wrt_access_graph ctxt) relearns |
1538 val access_G = access_G |> fold flop_wrt_access_graph flops |
1537 val access_G = access_G |> fold flop_wrt_access_graph flops |
1539 val num_known_facts = num_known_facts + length learns |
1538 val num_known_facts = num_known_facts + length learns |
1540 val dirty = |
1539 val dirty_facts = |
1541 (case (was_empty, dirty) of |
1540 (case (was_empty, dirty_facts) of |
1542 (false, SOME names) => SOME (map #1 learns @ map #1 relearns @ names) |
1541 (false, SOME names) => SOME (map #1 learns @ map #1 relearns @ names) |
1543 | _ => NONE) |
1542 | _ => NONE) |
1544 in |
1543 in |
1545 if engine = MaSh_Py then |
1544 if engine = MaSh_Py then |
1546 (MaSh_Py.learn ctxt overlord (save andalso null relearns) (rev learns); |
1545 (MaSh_Py.learn ctxt overlord (save andalso null relearns) (rev learns); |
1547 MaSh_Py.relearn ctxt overlord save relearns) |
1546 MaSh_Py.relearn ctxt overlord save relearns) |
1548 else |
1547 else |
1549 (); |
1548 (); |
1550 {access_G = access_G, num_known_facts = num_known_facts, dirty = dirty} |
1549 {access_G = access_G, num_known_facts = num_known_facts, dirty_facts = dirty_facts} |
1551 end |
1550 end |
1552 |
1551 |
1553 fun commit last learns relearns flops = |
1552 fun commit last learns relearns flops = |
1554 (if debug andalso auto_level = 0 then Output.urgent_message "Committing..." else (); |
1553 (if debug andalso auto_level = 0 then Output.urgent_message "Committing..." else (); |
1555 map_state ctxt overlord (do_commit (rev learns) relearns flops); |
1554 map_state ctxt overlord (do_commit (rev learns) relearns flops); |