157 |
157 |
158 |
158 |
159 (** global state -- document structure and execution process **) |
159 (** global state -- document structure and execution process **) |
160 |
160 |
161 abstype state = State of |
161 abstype state = State of |
162 {versions: version Inttab.table, (*version_id -> document content*) |
162 {versions: version Inttab.table, (*version_id -> document content*) |
163 commands: Toplevel.transition Inttab.table, (*command_id -> transition function*) |
163 commands: Toplevel.transition future Inttab.table, (*command_id -> transition (future parsing)*) |
164 execs: Toplevel.state option lazy Inttab.table, (*exec_id -> execution process*) |
164 execs: Toplevel.state option lazy Inttab.table, (*exec_id -> execution process*) |
165 execution: unit future list} (*global execution process*) |
165 execution: unit future list} (*global execution process*) |
166 with |
166 with |
167 |
167 |
168 fun make_state (versions, commands, execs, execution) = |
168 fun make_state (versions, commands, execs, execution) = |
169 State {versions = versions, commands = commands, execs = execs, execution = execution}; |
169 State {versions = versions, commands = commands, execs = execs, execution = execution}; |
170 |
170 |
171 fun map_state f (State {versions, commands, execs, execution}) = |
171 fun map_state f (State {versions, commands, execs, execution}) = |
172 make_state (f (versions, commands, execs, execution)); |
172 make_state (f (versions, commands, execs, execution)); |
173 |
173 |
174 val init_state = |
174 val init_state = |
175 make_state (Inttab.make [(no_id, empty_version)], |
175 make_state (Inttab.make [(no_id, empty_version)], |
176 Inttab.make [(no_id, Toplevel.empty)], |
176 Inttab.make [(no_id, Future.value Toplevel.empty)], |
177 Inttab.make [(no_id, Lazy.value (SOME Toplevel.toplevel))], |
177 Inttab.make [(no_id, Lazy.value (SOME Toplevel.toplevel))], |
178 []); |
178 []); |
179 |
179 |
180 |
180 |
181 (* document versions *) |
181 (* document versions *) |
196 |
196 |
197 fun define_command (id: command_id) text = |
197 fun define_command (id: command_id) text = |
198 map_state (fn (versions, commands, execs, execution) => |
198 map_state (fn (versions, commands, execs, execution) => |
199 let |
199 let |
200 val id_string = print_id id; |
200 val id_string = print_id id; |
201 val tr = |
201 val tr = Future.fork_pri 2 (fn () => |
202 Position.setmp_thread_data (Position.id_only id_string) |
202 Position.setmp_thread_data (Position.id_only id_string) |
203 (fn () => Outer_Syntax.prepare_command (Position.id id_string) text) (); |
203 (fn () => Outer_Syntax.prepare_command (Position.id id_string) text) ()); |
204 val commands' = |
204 val commands' = |
205 Inttab.update_new (id, Toplevel.put_id id_string tr) commands |
205 Inttab.update_new (id, tr) commands |
206 handle Inttab.DUP dup => err_dup "command" dup; |
206 handle Inttab.DUP dup => err_dup "command" dup; |
207 in (versions, commands', execs, execution) end); |
207 in (versions, commands', execs, execution) end); |
208 |
208 |
209 fun the_command (State {commands, ...}) (id: command_id) = |
209 fun the_command (State {commands, ...}) (id: command_id) = |
210 (case Inttab.lookup commands id of |
210 (case Inttab.lookup commands id of |
211 NONE => err_undef "command" id |
211 NONE => err_undef "command" id |
212 | SOME tr => tr); |
212 | SOME tr => tr); |
|
213 |
|
214 fun join_commands (State {commands, ...}) = |
|
215 Inttab.fold (fn (_, tr) => fn () => ignore (Future.join_result tr)) commands (); |
213 |
216 |
214 |
217 |
215 (* command executions *) |
218 (* command executions *) |
216 |
219 |
217 fun define_exec (id: exec_id) exec = |
220 fun define_exec (id: exec_id) exec = |
242 |
245 |
243 fun new_exec name (id: command_id) (exec_id, updates, state) = |
246 fun new_exec name (id: command_id) (exec_id, updates, state) = |
244 let |
247 let |
245 val exec = the_exec state exec_id; |
248 val exec = the_exec state exec_id; |
246 val exec_id' = new_id (); |
249 val exec_id' = new_id (); |
247 val tr = Toplevel.put_id (print_id exec_id') (the_command state id); |
250 val tr = the_command state id; |
248 val exec' = |
251 val exec' = |
249 Lazy.lazy (fn () => |
252 Lazy.lazy (fn () => |
250 (case Lazy.force exec of |
253 (case Lazy.force exec of |
251 NONE => NONE |
254 NONE => NONE |
252 | SOME st => Toplevel.run_command name tr st)); |
255 | SOME st => |
|
256 let val exec_tr = Toplevel.put_id (print_id exec_id') (Future.join tr) |
|
257 in Toplevel.run_command name exec_tr st end)); |
253 val state' = define_exec exec_id' exec' state; |
258 val state' = define_exec exec_id' exec' state; |
254 in (exec_id', (id, exec_id') :: updates, state') end; |
259 in (exec_id', (id, exec_id') :: updates, state') end; |
255 |
260 |
256 in |
261 in |
257 |
262 |
275 |
280 |
276 (* FIXME proper node deps *) |
281 (* FIXME proper node deps *) |
277 val (rev_updates, new_version', state') = |
282 val (rev_updates, new_version', state') = |
278 fold update_node (node_names_of new_version) ([], new_version, state); |
283 fold update_node (node_names_of new_version) ([], new_version, state); |
279 val state'' = define_version new_id new_version' state'; |
284 val state'' = define_version new_id new_version' state'; |
|
285 |
|
286 val _ = join_commands state''; (* FIXME async!? *) |
280 in (rev rev_updates, state'') end; |
287 in (rev rev_updates, state'') end; |
281 |
288 |
282 end; |
289 end; |
283 |
290 |
284 |
291 |