29 end; |
29 end; |
30 |
30 |
31 structure Document: DOCUMENT = |
31 structure Document: DOCUMENT = |
32 struct |
32 struct |
33 |
33 |
34 (* command execution *) |
|
35 |
|
36 type exec = Document_ID.exec * (Command.eval * Command.print list); (*eval/print process*) |
|
37 val no_exec: exec = (Document_ID.none, (Command.no_eval, [])); |
|
38 |
|
39 fun exec_ids_of ((exec_id, (_, prints)): exec) = exec_id :: map #exec_id prints; |
|
40 |
|
41 fun exec_result ((_, (eval, _)): exec) = Command.memo_result eval; |
|
42 |
|
43 fun exec_run ((_, (eval, prints)): exec) = |
|
44 (Command.memo_eval eval; |
|
45 prints |> List.app (fn {name, pri, print, ...} => |
|
46 Command.memo_fork {name = name, group = NONE, deps = [], pri = pri, interrupts = true} print)); |
|
47 |
|
48 |
|
49 |
|
50 (** document structure **) |
34 (** document structure **) |
51 |
35 |
52 fun err_dup kind id = error ("Duplicate " ^ kind ^ ": " ^ Document_ID.print id); |
36 fun err_dup kind id = error ("Duplicate " ^ kind ^ ": " ^ Document_ID.print id); |
53 fun err_undef kind id = error ("Undefined " ^ kind ^ ": " ^ Document_ID.print id); |
37 fun err_undef kind id = error ("Undefined " ^ kind ^ ": " ^ Document_ID.print id); |
54 |
38 |
57 structure Entries = Linear_Set(type key = Document_ID.command val ord = int_ord); |
41 structure Entries = Linear_Set(type key = Document_ID.command val ord = int_ord); |
58 |
42 |
59 abstype node = Node of |
43 abstype node = Node of |
60 {header: node_header, (*master directory, theory header, errors*) |
44 {header: node_header, (*master directory, theory header, errors*) |
61 perspective: perspective, (*visible commands, last visible command*) |
45 perspective: perspective, (*visible commands, last visible command*) |
62 entries: exec option Entries.T * bool, (*command entries with excecutions, stable*) |
46 entries: Command.exec option Entries.T * bool, (*command entries with excecutions, stable*) |
63 result: Command.eval option} (*result of last execution*) |
47 result: Command.eval option} (*result of last execution*) |
64 and version = Version of node String_Graph.T (*development graph wrt. static imports*) |
48 and version = Version of node String_Graph.T (*development graph wrt. static imports*) |
65 with |
49 with |
66 |
50 |
67 fun make_node (header, perspective, entries, result) = |
51 fun make_node (header, perspective, entries, result) = |
150 fun the_entry node id = |
134 fun the_entry node id = |
151 (case Entries.lookup (get_entries node) id of |
135 (case Entries.lookup (get_entries node) id of |
152 NONE => err_undef "command entry" id |
136 NONE => err_undef "command entry" id |
153 | SOME (exec, _) => exec); |
137 | SOME (exec, _) => exec); |
154 |
138 |
155 fun the_default_entry node (SOME id) = (id, the_default no_exec (the_entry node id)) |
139 fun the_default_entry node (SOME id) = (id, the_default Command.no_exec (the_entry node id)) |
156 | the_default_entry _ NONE = (Document_ID.none, no_exec); |
140 | the_default_entry _ NONE = (Document_ID.none, Command.no_exec); |
157 |
141 |
158 fun update_entry id exec = |
142 fun update_entry id exec = |
159 map_entries (Entries.update (id, exec)); |
143 map_entries (Entries.update (id, exec)); |
160 |
144 |
161 fun reset_entry id node = |
145 fun reset_entry id node = |
289 iterate_entries (fn ((_, id), _) => |
273 iterate_entries (fn ((_, id), _) => |
290 SOME o Inttab.insert (K true) (id, the_command state id)))); |
274 SOME o Inttab.insert (K true) (id, the_command state id)))); |
291 in (versions', commands', execution) end); |
275 in (versions', commands', execution) end); |
292 |
276 |
293 |
277 |
294 (* consolidated states *) |
|
295 |
|
296 fun stable_goals exec_id = |
|
297 not (Par_Exn.is_interrupted (Future.join_results (Goal.peek_futures exec_id))); |
|
298 |
|
299 fun stable_eval ((exec_id, (eval, _)): exec) = |
|
300 stable_goals exec_id andalso Command.memo_stable eval; |
|
301 |
|
302 fun stable_print ({exec_id, print, ...}: Command.print) = |
|
303 stable_goals exec_id andalso Command.memo_stable print; |
|
304 |
|
305 fun finished_theory node = |
278 fun finished_theory node = |
306 (case Exn.capture (Command.memo_result o the) (get_result node) of |
279 (case Exn.capture (Command.memo_result o the) (get_result node) of |
307 Exn.Res {state = st, ...} => can (Toplevel.end_theory Position.none) st |
280 Exn.Res {state = st, ...} => can (Toplevel.end_theory Position.none) st |
308 | _ => false); |
281 | _ => false); |
309 |
282 |
332 {name = "theory:" ^ name, group = SOME (Future.new_group (SOME group)), |
305 {name = "theory:" ^ name, group = SOME (Future.new_group (SOME group)), |
333 deps = map (Future.task_of o #2) deps, pri = ~2, interrupts = false} |
306 deps = map (Future.task_of o #2) deps, pri = ~2, interrupts = false} |
334 (fn () => |
307 (fn () => |
335 iterate_entries (fn (_, opt_exec) => fn () => |
308 iterate_entries (fn (_, opt_exec) => fn () => |
336 (case opt_exec of |
309 (case opt_exec of |
337 SOME exec => if ! running then SOME (exec_run exec) else NONE |
310 SOME exec => if ! running then SOME (Command.exec_run exec) else NONE |
338 | NONE => NONE)) node ())))); |
311 | NONE => NONE)) node ())))); |
339 in () end; |
312 in () end; |
340 |
313 |
341 |
314 |
342 |
315 |
404 (case opt_exec of |
377 (case opt_exec of |
405 NONE => false |
378 NONE => false |
406 | SOME (exec_id, exec) => |
379 | SOME (exec_id, exec) => |
407 (case lookup_entry node0 id of |
380 (case lookup_entry node0 id of |
408 NONE => false |
381 NONE => false |
409 | SOME (exec_id0, _) => exec_id = exec_id0 andalso stable_eval (exec_id, exec))); |
382 | SOME (exec_id0, _) => |
|
383 exec_id = exec_id0 andalso Command.stable_eval (exec_id, exec))); |
410 in SOME (same', (prev, flags')) end |
384 in SOME (same', (prev, flags')) end |
411 else NONE; |
385 else NONE; |
412 val (same, (common, flags)) = |
386 val (same, (common, flags)) = |
413 iterate_entries get_common node (true, (NONE, (true, true))); |
387 iterate_entries get_common node (true, (NONE, (true, true))); |
414 in |
388 in |
453 val (command_name, _) = the_command state command_id; |
427 val (command_name, _) = the_command state command_id; |
454 val new_prints = Command.print command_name eval; |
428 val new_prints = Command.print command_name eval; |
455 val prints' = |
429 val prints' = |
456 new_prints |> map (fn new_print => |
430 new_prints |> map (fn new_print => |
457 (case find_first (fn {name, ...} => name = #name new_print) prints of |
431 (case find_first (fn {name, ...} => name = #name new_print) prints of |
458 SOME print => if stable_print print then print else new_print |
432 SOME print => if Command.stable_print print then print else new_print |
459 | NONE => new_print)); |
433 | NONE => new_print)); |
460 in |
434 in |
461 if eq_list (op = o pairself #exec_id) (prints, prints') then NONE |
435 if eq_list (op = o pairself #exec_id) (prints, prints') then NONE |
462 else SOME (command_id, (exec_id, (eval, prints'))) |
436 else SOME (command_id, (exec_id, (eval, prints'))) |
463 end |
437 end |
546 end)) |
520 end)) |
547 |> Future.joins |> map #1); |
521 |> Future.joins |> map #1); |
548 |
522 |
549 val command_execs = |
523 val command_execs = |
550 map (rpair []) (maps #1 updated) @ |
524 map (rpair []) (maps #1 updated) @ |
551 map (fn (command_id, exec) => (command_id, exec_ids_of exec)) (maps #2 updated); |
525 map (fn (command_id, exec) => (command_id, Command.exec_ids exec)) (maps #2 updated); |
552 val updated_nodes = map_filter #3 updated; |
526 val updated_nodes = map_filter #3 updated; |
553 |
527 |
554 val state' = state |
528 val state' = state |
555 |> define_version new_id (fold put_node updated_nodes new_version); |
529 |> define_version new_id (fold put_node updated_nodes new_version); |
556 in (command_execs, state') end; |
530 in (command_execs, state') end; |