5 list of commands, with asynchronous read/eval/print processes. |
5 list of commands, with asynchronous read/eval/print processes. |
6 *) |
6 *) |
7 |
7 |
8 signature DOCUMENT = |
8 signature DOCUMENT = |
9 sig |
9 sig |
10 type id = int |
|
11 type version_id = id |
|
12 type command_id = id |
|
13 type exec_id = id |
|
14 val no_id: id |
|
15 val new_id: unit -> id |
|
16 val parse_id: string -> id |
|
17 val print_id: id -> string |
|
18 type node_header = string * Thy_Header.header * string list |
10 type node_header = string * Thy_Header.header * string list |
19 datatype node_edit = |
11 datatype node_edit = |
20 Clear | (* FIXME unused !? *) |
12 Clear | (* FIXME unused !? *) |
21 Edits of (command_id option * command_id option) list | |
13 Edits of (Document_ID.command option * Document_ID.command option) list | |
22 Deps of node_header | |
14 Deps of node_header | |
23 Perspective of command_id list |
15 Perspective of Document_ID.command list |
24 type edit = string * node_edit |
16 type edit = string * node_edit |
25 type state |
17 type state |
26 val init_state: state |
18 val init_state: state |
27 val define_command: command_id -> string -> string -> state -> state |
19 val define_command: Document_ID.command -> string -> string -> state -> state |
28 val remove_versions: version_id list -> state -> state |
20 val remove_versions: Document_ID.version list -> state -> state |
29 val discontinue_execution: state -> unit |
21 val discontinue_execution: state -> unit |
30 val cancel_execution: state -> unit |
22 val cancel_execution: state -> unit |
31 val start_execution: state -> unit |
23 val start_execution: state -> unit |
32 val timing: bool Unsynchronized.ref |
24 val timing: bool Unsynchronized.ref |
33 val update: version_id -> version_id -> edit list -> state -> |
25 val update: Document_ID.version -> Document_ID.version -> edit list -> state -> |
34 (command_id * exec_id list) list * state |
26 (Document_ID.command * Document_ID.exec list) list * state |
35 val state: unit -> state |
27 val state: unit -> state |
36 val change_state: (state -> state) -> unit |
28 val change_state: (state -> state) -> unit |
37 end; |
29 end; |
38 |
30 |
39 structure Document: DOCUMENT = |
31 structure Document: DOCUMENT = |
40 struct |
32 struct |
41 |
33 |
42 (* unique identifiers *) |
|
43 |
|
44 type id = int; |
|
45 type version_id = id; |
|
46 type command_id = id; |
|
47 type exec_id = id; |
|
48 |
|
49 val no_id = 0; |
|
50 val new_id = Synchronized.counter (); |
|
51 |
|
52 val parse_id = Markup.parse_int; |
|
53 val print_id = Markup.print_int; |
|
54 |
|
55 fun err_dup kind id = error ("Duplicate " ^ kind ^ ": " ^ print_id id); |
|
56 fun err_undef kind id = error ("Undefined " ^ kind ^ ": " ^ print_id id); |
|
57 |
|
58 |
|
59 (* command execution *) |
34 (* command execution *) |
60 |
35 |
61 type exec = exec_id * (Command.eval * Command.print list); (*eval/print process*) |
36 type exec = Document_ID.exec * (Command.eval * Command.print list); (*eval/print process*) |
62 val no_exec: exec = (no_id, (Command.no_eval, [])); |
37 val no_exec: exec = (Document_ID.none, (Command.no_eval, [])); |
63 |
38 |
64 fun exec_ids_of ((exec_id, (_, prints)): exec) = exec_id :: map #exec_id prints; |
39 fun exec_ids_of ((exec_id, (_, prints)): exec) = exec_id :: map #exec_id prints; |
65 |
40 |
66 fun exec_result ((_, (eval, _)): exec) = Command.memo_result eval; |
41 fun exec_result ((_, (eval, _)): exec) = Command.memo_result eval; |
67 |
42 |
72 |
47 |
73 |
48 |
74 |
49 |
75 (** document structure **) |
50 (** document structure **) |
76 |
51 |
|
52 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); |
|
54 |
77 type node_header = string * Thy_Header.header * string list; |
55 type node_header = string * Thy_Header.header * string list; |
78 type perspective = Inttab.set * command_id option; |
56 type perspective = Inttab.set * Document_ID.command option; |
79 structure Entries = Linear_Set(type key = command_id val ord = int_ord); |
57 structure Entries = Linear_Set(type key = Document_ID.command val ord = int_ord); |
80 |
58 |
81 abstype node = Node of |
59 abstype node = Node of |
82 {header: node_header, (*master directory, theory header, errors*) |
60 {header: node_header, (*master directory, theory header, errors*) |
83 perspective: perspective, (*visible commands, last visible command*) |
61 perspective: perspective, (*visible commands, last visible command*) |
84 entries: exec option Entries.T * bool, (*command entries with excecutions, stable*) |
62 entries: exec option Entries.T * bool, (*command entries with excecutions, stable*) |
173 (case Entries.lookup (get_entries node) id of |
151 (case Entries.lookup (get_entries node) id of |
174 NONE => err_undef "command entry" id |
152 NONE => err_undef "command entry" id |
175 | SOME (exec, _) => exec); |
153 | SOME (exec, _) => exec); |
176 |
154 |
177 fun the_default_entry node (SOME id) = (id, the_default no_exec (the_entry node id)) |
155 fun the_default_entry node (SOME id) = (id, the_default no_exec (the_entry node id)) |
178 | the_default_entry _ NONE = (no_id, no_exec); |
156 | the_default_entry _ NONE = (Document_ID.none, no_exec); |
179 |
157 |
180 fun update_entry id exec = |
158 fun update_entry id exec = |
181 map_entries (Entries.update (id, exec)); |
159 map_entries (Entries.update (id, exec)); |
182 |
160 |
183 fun reset_entry id node = |
161 fun reset_entry id node = |
235 (** main state -- document structure and execution process **) |
213 (** main state -- document structure and execution process **) |
236 |
214 |
237 abstype state = State of |
215 abstype state = State of |
238 {versions: version Inttab.table, (*version_id -> document content*) |
216 {versions: version Inttab.table, (*version_id -> document content*) |
239 commands: (string * Token.T list lazy) Inttab.table, (*command_id -> named span*) |
217 commands: (string * Token.T list lazy) Inttab.table, (*command_id -> named span*) |
240 execution: version_id * Future.group * bool Unsynchronized.ref} (*current execution process*) |
218 execution: |
|
219 Document_ID.version * Future.group * bool Unsynchronized.ref} (*current execution process*) |
241 with |
220 with |
242 |
221 |
243 fun make_state (versions, commands, execution) = |
222 fun make_state (versions, commands, execution) = |
244 State {versions = versions, commands = commands, execution = execution}; |
223 State {versions = versions, commands = commands, execution = execution}; |
245 |
224 |
246 fun map_state f (State {versions, commands, execution}) = |
225 fun map_state f (State {versions, commands, execution}) = |
247 make_state (f (versions, commands, execution)); |
226 make_state (f (versions, commands, execution)); |
248 |
227 |
249 val init_state = |
228 val init_state = |
250 make_state (Inttab.make [(no_id, empty_version)], Inttab.empty, |
229 make_state (Inttab.make [(Document_ID.none, empty_version)], Inttab.empty, |
251 (no_id, Future.new_group NONE, Unsynchronized.ref false)); |
230 (Document_ID.none, Future.new_group NONE, Unsynchronized.ref false)); |
252 |
231 |
253 fun execution_of (State {execution, ...}) = execution; |
232 fun execution_of (State {execution, ...}) = execution; |
254 |
233 |
255 |
234 |
256 (* document versions *) |
235 (* document versions *) |
257 |
236 |
258 fun define_version (id: version_id) version = |
237 fun define_version (id: Document_ID.version) version = |
259 map_state (fn (versions, commands, _) => |
238 map_state (fn (versions, commands, _) => |
260 let |
239 let |
261 val versions' = Inttab.update_new (id, version) versions |
240 val versions' = Inttab.update_new (id, version) versions |
262 handle Inttab.DUP dup => err_dup "document version" dup; |
241 handle Inttab.DUP dup => err_dup "document version" dup; |
263 val execution' = (id, Future.new_group NONE, Unsynchronized.ref true); |
242 val execution' = (id, Future.new_group NONE, Unsynchronized.ref true); |
264 in (versions', commands, execution') end); |
243 in (versions', commands, execution') end); |
265 |
244 |
266 fun the_version (State {versions, ...}) (id: version_id) = |
245 fun the_version (State {versions, ...}) (id: Document_ID.version) = |
267 (case Inttab.lookup versions id of |
246 (case Inttab.lookup versions id of |
268 NONE => err_undef "document version" id |
247 NONE => err_undef "document version" id |
269 | SOME version => version); |
248 | SOME version => version); |
270 |
249 |
271 fun delete_version (id: version_id) versions = Inttab.delete id versions |
250 fun delete_version (id: Document_ID.version) versions = Inttab.delete id versions |
272 handle Inttab.UNDEF _ => err_undef "document version" id; |
251 handle Inttab.UNDEF _ => err_undef "document version" id; |
273 |
252 |
274 |
253 |
275 (* commands *) |
254 (* commands *) |
276 |
255 |
277 fun define_command (id: command_id) name text = |
256 fun define_command (id: Document_ID.command) name text = |
278 map_state (fn (versions, commands, execution) => |
257 map_state (fn (versions, commands, execution) => |
279 let |
258 let |
280 val id_string = print_id id; |
259 val id_string = Document_ID.print id; |
281 val span = Lazy.lazy (fn () => |
260 val span = Lazy.lazy (fn () => |
282 Position.setmp_thread_data (Position.id_only id_string) |
261 Position.setmp_thread_data (Position.id_only id_string) |
283 (fn () => Thy_Syntax.parse_tokens (Keyword.get_lexicons ()) (Position.id id_string) text) |
262 (fn () => Thy_Syntax.parse_tokens (Keyword.get_lexicons ()) (Position.id id_string) text) |
284 ()); |
263 ()); |
285 val _ = |
264 val _ = |
288 val commands' = |
267 val commands' = |
289 Inttab.update_new (id, (name, span)) commands |
268 Inttab.update_new (id, (name, span)) commands |
290 handle Inttab.DUP dup => err_dup "command" dup; |
269 handle Inttab.DUP dup => err_dup "command" dup; |
291 in (versions, commands', execution) end); |
270 in (versions, commands', execution) end); |
292 |
271 |
293 fun the_command (State {commands, ...}) (id: command_id) = |
272 fun the_command (State {commands, ...}) (id: Document_ID.command) = |
294 (case Inttab.lookup commands id of |
273 (case Inttab.lookup commands id of |
295 NONE => err_undef "command" id |
274 NONE => err_undef "command" id |
296 | SOME command => command); |
275 | SOME command => command); |
297 |
276 |
298 end; |
277 end; |
299 |
278 |
300 fun remove_versions ids state = state |> map_state (fn (versions, _, execution) => |
279 fun remove_versions ids state = state |> map_state (fn (versions, _, execution) => |
301 let |
280 let |
302 val _ = member (op =) ids (#1 execution) andalso |
281 val _ = member (op =) ids (#1 execution) andalso |
303 error ("Attempt to remove execution version " ^ print_id (#1 execution)); |
282 error ("Attempt to remove execution version " ^ Document_ID.print (#1 execution)); |
304 |
283 |
305 val versions' = fold delete_version ids versions; |
284 val versions' = fold delete_version ids versions; |
306 val commands' = |
285 val commands' = |
307 (versions', Inttab.empty) |-> |
286 (versions', Inttab.empty) |-> |
308 Inttab.fold (fn (_, version) => nodes_of version |> |
287 Inttab.fold (fn (_, version) => nodes_of version |> |
449 val (modify_init, init') = |
428 val (modify_init, init') = |
450 if Keyword.is_theory_begin command_name then |
429 if Keyword.is_theory_begin command_name then |
451 (Toplevel.modify_init (fn () => the_default illegal_init init span), NONE) |
430 (Toplevel.modify_init (fn () => the_default illegal_init init span), NONE) |
452 else (I, init); |
431 else (I, init); |
453 |
432 |
454 val exec_id' = new_id (); |
433 val exec_id' = Document_ID.make (); |
455 val eval' = |
434 val eval' = |
456 Command.memo (fn () => |
435 Command.memo (fn () => |
457 let |
436 let |
458 val eval_state = exec_result (snd command_exec); |
437 val eval_state = exec_result (snd command_exec); |
459 val tr = |
438 val tr = |
460 Position.setmp_thread_data (Position.id_only (print_id exec_id')) |
439 Position.setmp_thread_data (Position.id_only (Document_ID.print exec_id')) |
461 (fn () => |
440 (fn () => |
462 Command.read span |
441 Command.read span |
463 |> modify_init |
442 |> modify_init |
464 |> Toplevel.put_id exec_id') (); |
443 |> Toplevel.put_id exec_id') (); |
465 in Command.eval span tr eval_state end); |
444 in Command.eval span tr eval_state end); |
466 val prints' = if command_visible then Command.print new_id command_name eval' else []; |
445 val prints' = if command_visible then Command.print command_name eval' else []; |
467 val command_exec' = (command_id', (exec_id', (eval', prints'))); |
446 val command_exec' = (command_id', (exec_id', (eval', prints'))); |
468 in SOME (command_exec' :: execs, command_exec', init') end; |
447 in SOME (command_exec' :: execs, command_exec', init') end; |
469 |
448 |
470 fun update_prints state node command_id = |
449 fun update_prints state node command_id = |
471 (case the_entry node command_id of |
450 (case the_entry node command_id of |
472 SOME (exec_id, (eval, prints)) => |
451 SOME (exec_id, (eval, prints)) => |
473 let |
452 let |
474 val (command_name, _) = the_command state command_id; |
453 val (command_name, _) = the_command state command_id; |
475 val new_prints = Command.print new_id command_name eval; |
454 val new_prints = Command.print command_name eval; |
476 val prints' = |
455 val prints' = |
477 new_prints |> map (fn new_print => |
456 new_prints |> map (fn new_print => |
478 (case find_first (fn {name, ...} => name = #name new_print) prints of |
457 (case find_first (fn {name, ...} => name = #name new_print) prints of |
479 SOME print => if stable_print print then print else new_print |
458 SOME print => if stable_print print then print else new_print |
480 | NONE => new_print)); |
459 | NONE => new_print)); |