28 val cancel_execution: state -> Future.task list |
28 val cancel_execution: state -> Future.task list |
29 val update_perspective: version_id -> version_id -> string -> command_id list -> state -> state |
29 val update_perspective: version_id -> version_id -> string -> command_id list -> state -> state |
30 val update: version_id -> version_id -> edit list -> state -> |
30 val update: version_id -> version_id -> edit list -> state -> |
31 ((command_id * exec_id option) list * (string * command_id option) list) * state |
31 ((command_id * exec_id option) list * (string * command_id option) list) * state |
32 val execute: version_id -> state -> state |
32 val execute: version_id -> state -> state |
|
33 val remove_versions: version_id list -> state -> state |
33 val state: unit -> state |
34 val state: unit -> state |
34 val change_state: (state -> state) -> unit |
35 val change_state: (state -> state) -> unit |
35 end; |
36 end; |
36 |
37 |
37 structure Document: DOCUMENT = |
38 structure Document: DOCUMENT = |
237 abstype state = State of |
238 abstype state = State of |
238 {versions: version Inttab.table, (*version_id -> document content*) |
239 {versions: version Inttab.table, (*version_id -> document content*) |
239 commands: (string * Toplevel.transition future) Inttab.table, (*command_id -> name * transition*) |
240 commands: (string * Toplevel.transition future) Inttab.table, (*command_id -> name * transition*) |
240 execs: (command_id * (Toplevel.state * unit lazy) lazy) Inttab.table, |
241 execs: (command_id * (Toplevel.state * unit lazy) lazy) Inttab.table, |
241 (*exec_id -> command_id with eval/print process*) |
242 (*exec_id -> command_id with eval/print process*) |
242 execution: Future.group} (*global execution process*) |
243 execution: version_id * Future.group} (*current execution process*) |
243 with |
244 with |
244 |
245 |
245 fun make_state (versions, commands, execs, execution) = |
246 fun make_state (versions, commands, execs, execution) = |
246 State {versions = versions, commands = commands, execs = execs, execution = execution}; |
247 State {versions = versions, commands = commands, execs = execs, execution = execution}; |
247 |
248 |
248 fun map_state f (State {versions, commands, execs, execution}) = |
249 fun map_state f (State {versions, commands, execs, execution}) = |
249 make_state (f (versions, commands, execs, execution)); |
250 make_state (f (versions, commands, execs, execution)); |
250 |
251 |
|
252 val empty_commands = |
|
253 Inttab.make [(no_id, (Toplevel.name_of Toplevel.empty, Future.value Toplevel.empty))]; |
|
254 val empty_execs = Inttab.make [(no_id, (no_id, Lazy.value (Toplevel.toplevel, no_print)))]; |
|
255 val empty_execution = (no_id, Future.new_group NONE); |
|
256 |
251 val init_state = |
257 val init_state = |
252 make_state (Inttab.make [(no_id, empty_version)], |
258 make_state (Inttab.make [(no_id, empty_version)], empty_commands, empty_execs, empty_execution); |
253 Inttab.make [(no_id, (Toplevel.name_of Toplevel.empty, Future.value Toplevel.empty))], |
|
254 Inttab.make [(no_id, (no_id, Lazy.value (Toplevel.toplevel, no_print)))], |
|
255 Future.new_group NONE); |
|
256 |
259 |
257 |
260 |
258 (* document versions *) |
261 (* document versions *) |
259 |
262 |
260 fun define_version (id: version_id) version = |
263 fun define_version (id: version_id) version = |
265 |
268 |
266 fun the_version (State {versions, ...}) (id: version_id) = |
269 fun the_version (State {versions, ...}) (id: version_id) = |
267 (case Inttab.lookup versions id of |
270 (case Inttab.lookup versions id of |
268 NONE => err_undef "document version" id |
271 NONE => err_undef "document version" id |
269 | SOME version => version); |
272 | SOME version => version); |
|
273 |
|
274 fun delete_version (id: version_id) versions = Inttab.delete id versions |
|
275 handle Inttab.UNDEF _ => err_undef "document version" id; |
270 |
276 |
271 |
277 |
272 (* commands *) |
278 (* commands *) |
273 |
279 |
274 fun define_command (id: command_id) name text = |
280 fun define_command (id: command_id) name text = |
551 if #1 (get_perspective node) command_id |
557 if #1 (get_perspective node) command_id |
552 then ignore (Lazy.future Future.default_params print) |
558 then ignore (Lazy.future Future.default_params print) |
553 else (); |
559 else (); |
554 in () end; |
560 in () end; |
555 |
561 |
556 val execution = Future.new_group NONE; |
562 val group = Future.new_group NONE; |
557 val _ = |
563 val _ = |
558 nodes_of version |> Graph.schedule |
564 nodes_of version |> Graph.schedule |
559 (fn deps => fn (name, node) => |
565 (fn deps => fn (name, node) => |
560 (singleton o Future.forks) |
566 (singleton o Future.forks) |
561 {name = "theory:" ^ name, group = SOME (Future.new_group (SOME execution)), |
567 {name = "theory:" ^ name, group = SOME (Future.new_group (SOME group)), |
562 deps = map (Future.task_of o #2) deps, pri = 1, interrupts = false} |
568 deps = map (Future.task_of o #2) deps, pri = 1, interrupts = false} |
563 (iterate_entries (fn (_, exec) => fn () => SOME (force_exec node exec)) node)); |
569 (iterate_entries (fn (_, exec) => fn () => SOME (force_exec node exec)) node)); |
564 |
570 |
565 in (versions, commands, execs, execution) end); |
571 in (versions, commands, execs, (version_id, group)) end); |
|
572 |
|
573 |
|
574 (* remove versions *) |
|
575 |
|
576 fun remove_versions ids state = state |> map_state (fn (versions, _, _, execution) => |
|
577 let |
|
578 val _ = member (op =) ids (#1 execution) andalso |
|
579 error ("Attempt to remove execution version " ^ print_id (#1 execution)); |
|
580 |
|
581 val versions' = fold delete_version ids versions; |
|
582 val (commands', execs') = |
|
583 (versions', (empty_commands, empty_execs)) |-> |
|
584 Inttab.fold (fn (_, version) => nodes_of version |> |
|
585 Graph.fold (fn (_, (node, _)) => node |> |
|
586 iterate_entries (fn ((_, id), exec) => fn (commands, execs) => |
|
587 let |
|
588 val commands' = Inttab.insert (K true) (id, the_command state id) commands; |
|
589 val execs' = |
|
590 (case exec of |
|
591 NONE => execs |
|
592 | SOME exec_id => Inttab.insert (K true) (exec_id, the_exec state exec_id) execs); |
|
593 in SOME (commands', execs') end))); |
|
594 in (versions', commands', execs', execution) end); |
566 |
595 |
567 |
596 |
568 |
597 |
569 (** global state **) |
598 (** global state **) |
570 |
599 |