define_state/new_state: provide state immediately, which is now lazy;
authorwenzelm
Sat, 29 May 2010 16:44:44 +0200
changeset 37184 79fe8e753e84
parent 37183 dae865999db5
child 37185 64da21a2c6c7
define_state/new_state: provide state immediately, which is now lazy; more careful document editing: single execution future forces all entries, synchronous cancelation after update;
src/Pure/Isar/isar_document.ML
--- a/src/Pure/Isar/isar_document.ML	Sat May 29 15:52:47 2010 +0200
+++ b/src/Pure/Isar/isar_document.ML	Sat May 29 16:44:44 2010 +0200
@@ -111,21 +111,17 @@
 
 (* states *)
 
-val empty_state = Lazy.value (SOME Toplevel.toplevel);
+local
 
-local
-  val global_states = Unsynchronized.ref (Symtab.make [(no_id, empty_state)]);
+val global_states = Unsynchronized.ref (Symtab.make [(no_id, Lazy.value (SOME Toplevel.toplevel))]);
+
 in
 
-fun define_state (id: state_id) =
+fun define_state (id: state_id) state =
   NAMED_CRITICAL "Isar" (fn () =>
-    Unsynchronized.change global_states (Symtab.update_new (id, empty_state))
+    Unsynchronized.change global_states (Symtab.update_new (id, state))
       handle Symtab.DUP dup => err_dup "state" dup);
 
-fun put_state (id: state_id) state =
-  NAMED_CRITICAL "Isar" (fn () =>
-    Unsynchronized.change global_states (Symtab.update (id, state)));
-
 fun the_state (id: state_id) =
   (case Symtab.lookup (! global_states) id of
     NONE => err_undef "state" id
@@ -137,10 +133,12 @@
 (* commands *)
 
 local
-  val global_commands = Unsynchronized.ref (Symtab.make [(no_id, Toplevel.empty)]);
+
+val global_commands = Unsynchronized.ref (Symtab.make [(no_id, Toplevel.empty)]);
+
 in
 
-fun define_command id tr =
+fun define_command (id: command_id) tr =
   NAMED_CRITICAL "Isar" (fn () =>
     Unsynchronized.change global_commands (Symtab.update_new (id, Toplevel.put_id id tr))
       handle Symtab.DUP dup => err_dup "command" dup);
@@ -156,7 +154,9 @@
 (* documents *)
 
 local
-  val global_documents = Unsynchronized.ref (Symtab.empty: document Symtab.table);
+
+val global_documents = Unsynchronized.ref (Symtab.empty: document Symtab.table);
+
 in
 
 fun define_document (id: document_id) document =
@@ -172,18 +172,6 @@
 end;
 
 
-(* execution *)
-
-local
-  val execution = Unsynchronized.ref (Future.value ());
-in
-
-fun execute e =
-  NAMED_CRITICAL "Isar" (fn () => (Future.cancel (! execution); execution := Future.fork e));
-
-end;
-
-
 
 (** main operations **)
 
@@ -224,27 +212,40 @@
     NONE => true
   | SOME {next = _, state = state'} => state' <> state);
 
-fun new_state name (id, _) (state_id, updates) =
+fun new_state name (id: command_id) (state_id, updates) =
   let
+    val state = the_state state_id;
     val state_id' = create_id ();
-    val _ = define_state state_id';
     val tr = Toplevel.put_id state_id' (the_command id);
-    fun make_state' () =
-      let
-        val state = the_state state_id;
-        val state' =
-          Lazy.lazy (fn () =>
-            (case Lazy.force state of
-              NONE => NONE
-            | SOME st => Toplevel.run_command name tr st));
-      in put_state state_id' state'; state' end;
-  in (state_id', ((id, state_id'), make_state') :: updates) end;
+    val state' =
+      Lazy.lazy (fn () =>
+        (case Lazy.force state of
+          NONE => NONE
+        | SOME st => Toplevel.run_command name tr st));
+    val _ = define_state state_id' state';
+  in (state_id', (id, state_id') :: updates) end;
 
 fun report_updates updates =
   implode (map (fn (id, state_id) => Markup.markup (Markup.edit id state_id) "") updates)
   |> Markup.markup Markup.assign
   |> Output.status;
 
+
+fun force_state NONE = ()
+  | force_state (SOME state_id) = ignore (Lazy.force (the_state state_id));
+
+val execution = Unsynchronized.ref (Future.value ());
+
+fun execute document =
+  NAMED_CRITICAL "Isar" (fn () =>
+    let
+      val old_execution = ! execution;
+      val _ = Future.cancel old_execution;
+      val new_execution = Future.fork (fn () =>
+       (Future.join_result old_execution;
+        fold_entries no_id (fn (_, {state, ...}) => fn () => force_state state) document ()));
+    in execution := new_execution end);
+
 in
 
 fun edit_document (old_id: document_id) (new_id: document_id) edits =
@@ -260,14 +261,14 @@
         | SOME (prev, id, _) =>
             let
               val prev_state_id = the (#state (the_entry new_entries (the prev)));
-              val (_, updates) = fold_entries id (new_state name) new_document (prev_state_id, []);
-              val new_document' = new_document |> map_entries (fold (set_entry_state o #1) updates);
+              val (_, updates) =
+                fold_entries id (new_state name o #1) new_document (prev_state_id, []);
+              val new_document' = new_document |> map_entries (fold set_entry_state updates);
             in (rev updates, new_document') end);
 
       val _ = define_document new_id new_document';
-      val _ = report_updates (map #1 updates);
-      val execs = map (fn (_, make) => make ()) updates;
-      val _ = execute (fn () => List.app (ignore o Lazy.force) execs);
+      val _ = report_updates updates;
+      val _ = execute new_document';
     in () end);
 
 end;