57 |
57 |
58 |
58 |
59 (** document structure **) |
59 (** document structure **) |
60 |
60 |
61 type node_header = (string * Thy_Header.header) Exn.result; |
61 type node_header = (string * Thy_Header.header) Exn.result; |
62 type perspective = (command_id -> bool) * command_id option; (*visible commands, last*) |
62 type perspective = (command_id -> bool) * command_id option; |
63 structure Entries = Linear_Set(type key = command_id val ord = int_ord); |
63 structure Entries = Linear_Set(type key = command_id val ord = int_ord); |
64 |
64 |
65 type exec = (Toplevel.state * unit lazy) Command.memo; (*eval/print process*) |
65 type exec = (Toplevel.state * unit lazy) Command.memo; (*eval/print process*) |
66 val no_exec = Command.memo_value (Toplevel.toplevel, Lazy.value ()); |
66 val no_exec = Command.memo_value (Toplevel.toplevel, Lazy.value ()); |
67 |
67 |
68 abstype node = Node of |
68 abstype node = Node of |
69 {header: node_header, |
69 {header: node_header, |
70 perspective: perspective, |
70 perspective: perspective, (*visible commands, last*) |
71 entries: (exec_id * exec) option Entries.T, (*command entries with excecutions*) |
71 entries: (exec_id * exec) option Entries.T, (*command entries with excecutions*) |
72 result: exec} |
72 result: exec option} (*result of last execution*) |
73 and version = Version of node Graph.T (*development graph wrt. static imports*) |
73 and version = Version of node Graph.T (*development graph wrt. static imports*) |
74 with |
74 with |
75 |
75 |
76 fun make_node (header, perspective, entries, result) = |
76 fun make_node (header, perspective, entries, result) = |
77 Node {header = header, perspective = perspective, entries = entries, result = result}; |
77 Node {header = header, perspective = perspective, entries = entries, result = result}; |
83 (Inttab.defined (Inttab.make (map (rpair ()) command_ids)), try List.last command_ids); |
83 (Inttab.defined (Inttab.make (map (rpair ()) command_ids)), try List.last command_ids); |
84 |
84 |
85 val no_header = Exn.Exn (ERROR "Bad theory header"); |
85 val no_header = Exn.Exn (ERROR "Bad theory header"); |
86 val no_perspective = make_perspective []; |
86 val no_perspective = make_perspective []; |
87 |
87 |
88 val empty_node = make_node (no_header, no_perspective, Entries.empty, no_exec); |
88 val empty_node = make_node (no_header, no_perspective, Entries.empty, NONE); |
89 val clear_node = map_node (fn (header, _, _, _) => (header, no_perspective, Entries.empty, no_exec)); |
89 val clear_node = map_node (fn (header, _, _, _) => (header, no_perspective, Entries.empty, NONE)); |
90 |
90 |
91 |
91 |
92 (* basic components *) |
92 (* basic components *) |
93 |
93 |
94 fun get_header (Node {header, ...}) = header; |
94 fun get_header (Node {header, ...}) = header; |
328 |
328 |
329 local |
329 local |
330 |
330 |
331 fun stable_finished_theory node = |
331 fun stable_finished_theory node = |
332 is_some (Exn.get_res (Exn.capture (fn () => |
332 is_some (Exn.get_res (Exn.capture (fn () => |
333 fst (Command.memo_result (get_result node)) |
333 fst (Command.memo_result (the (get_result node))) |
334 |> Toplevel.end_theory Position.none |
334 |> Toplevel.end_theory Position.none |
335 |> Global_Theory.join_proofs) ())); |
335 |> Global_Theory.join_proofs) ())); |
336 |
336 |
337 fun stable_command exec = |
337 fun stable_command exec = |
338 (case Exn.capture Command.memo_result exec of |
338 (case Exn.capture Command.memo_result exec of |
363 (case Url.explode dir of |
363 (case Url.explode dir of |
364 Url.File path => path |
364 Url.File path => path |
365 | _ => Path.current); |
365 | _ => Path.current); |
366 val parents = |
366 val parents = |
367 #imports header |> map (fn import => |
367 #imports header |> map (fn import => |
368 (case Thy_Info.lookup_theory import of (* FIXME more robust!? *) |
368 (case Thy_Info.lookup_theory import of |
369 SOME thy => thy |
369 SOME thy => thy |
370 | NONE => |
370 | NONE => |
371 Toplevel.end_theory (Position.file_only import) |
371 Toplevel.end_theory (Position.file_only import) |
372 (fst (Command.memo_result |
372 (fst |
373 (get_result (snd (the (AList.lookup (op =) imports import)))))))); |
373 (Command.memo_result |
|
374 (the_default no_exec |
|
375 (get_result (snd (the (AList.lookup (op =) imports import))))))))); |
374 in Thy_Load.begin_theory master_dir header parents end; |
376 in Thy_Load.begin_theory master_dir header parents end; |
375 |
377 |
376 fun check_theory nodes name = |
378 fun check_theory full name node = |
377 is_some (Thy_Info.lookup_theory name) orelse (* FIXME more robust!? *) |
379 is_some (Thy_Info.lookup_theory name) orelse |
378 is_some (Exn.get_res (get_header (get_node nodes name))); |
380 is_some (Exn.get_res (get_header node)) andalso (not full orelse is_some (get_result node)); |
379 |
381 |
380 fun last_common state last_visible node0 node = |
382 fun last_common state last_visible node0 node = |
381 let |
383 let |
382 fun update_flags prev (visible, initial) = |
384 fun update_flags prev (visible, initial) = |
383 let |
385 let |
408 in (last, update_flags last flags) end |
410 in (last, update_flags last flags) end |
409 end; |
411 end; |
410 |
412 |
411 fun illegal_init () = error "Illegal theory header after end of theory"; |
413 fun illegal_init () = error "Illegal theory header after end of theory"; |
412 |
414 |
413 fun new_exec state bad_init command_id' (execs, command_exec, init) = |
415 fun new_exec state proper_init command_id' (execs, command_exec, init) = |
414 if bad_init andalso is_none init then NONE |
416 if not proper_init andalso is_none init then NONE |
415 else |
417 else |
416 let |
418 let |
417 val (name, span) = the_command state command_id' ||> Lazy.force; |
419 val (name, span) = the_command state command_id' ||> Lazy.force; |
418 val (modify_init, init') = |
420 val (modify_init, init') = |
419 if Keyword.is_theory_begin name then |
421 if Keyword.is_theory_begin name then |
461 required andalso not (stable_finished_theory node) |
463 required andalso not (stable_finished_theory node) |
462 then |
464 then |
463 let |
465 let |
464 val node0 = node_of old_version name; |
466 val node0 = node_of old_version name; |
465 fun init () = init_theory imports node; |
467 fun init () = init_theory imports node; |
466 val bad_init = |
468 val proper_init = |
467 not (check_theory nodes name andalso forall (check_theory nodes o #1) imports); |
469 check_theory false name node andalso |
|
470 forall (fn (name, (_, node)) => check_theory true name node) imports; |
468 |
471 |
469 val last_visible = visible_last node; |
472 val last_visible = visible_last node; |
470 val (common, (visible, initial)) = |
473 val (common, (visible, initial)) = |
471 if updated_imports then (NONE, (true, true)) |
474 if updated_imports then (NONE, (true, true)) |
472 else last_common state last_visible node0 node; |
475 else last_common state last_visible node0 node; |
476 ([], common_command_exec, if initial then SOME init else NONE) |> |
479 ([], common_command_exec, if initial then SOME init else NONE) |> |
477 (visible orelse required) ? |
480 (visible orelse required) ? |
478 iterate_entries_after common |
481 iterate_entries_after common |
479 (fn ((prev, id), _) => fn res => |
482 (fn ((prev, id), _) => fn res => |
480 if not required andalso prev = last_visible then NONE |
483 if not required andalso prev = last_visible then NONE |
481 else new_exec state bad_init id res) node; |
484 else new_exec state proper_init id res) node; |
482 |
485 |
483 val no_execs = |
486 val no_execs = |
484 iterate_entries_after common |
487 iterate_entries_after common |
485 (fn ((_, id0), exec0) => fn res => |
488 (fn ((_, id0), exec0) => fn res => |
486 if is_none exec0 then NONE |
489 if is_none exec0 then NONE |
487 else if exists (fn (_, (id, _)) => id0 = id) new_execs then SOME res |
490 else if exists (fn (_, (id, _)) => id0 = id) new_execs then SOME res |
488 else SOME (id0 :: res)) node0 []; |
491 else SOME (id0 :: res)) node0 []; |
489 |
492 |
490 val last_exec = if command_id' = no_id then NONE else SOME command_id'; |
493 val last_exec = if command_id' = no_id then NONE else SOME command_id'; |
491 val result = |
494 val result = |
492 if is_some (after_entry node last_exec) then no_exec |
495 if is_some (after_entry node last_exec) then NONE |
493 else exec'; |
496 else SOME exec'; |
494 |
497 |
495 val node' = node |
498 val node' = node |
496 |> fold reset_entry no_execs |
499 |> fold reset_entry no_execs |
497 |> fold (fn (id, exec) => update_entry id (SOME exec)) new_execs |
500 |> fold (fn (id, exec) => update_entry id (SOME exec)) new_execs |
498 |> set_result result; |
501 |> set_result result; |