src/Pure/PIDE/document.ML
changeset 44185 05641edb5d30
parent 44182 ecb51b457064
child 44186 806f0ec1a43d
equal deleted inserted replaced
44184:49501dc1a7b8 44185:05641edb5d30
    13   type exec_id = id
    13   type exec_id = id
    14   val no_id: id
    14   val no_id: id
    15   val new_id: unit -> id
    15   val new_id: unit -> id
    16   val parse_id: string -> id
    16   val parse_id: string -> id
    17   val print_id: id -> string
    17   val print_id: id -> string
    18   type node_header = (string * string list * string list) Exn.result
    18   type node_header = (string * string list * (string * bool) list) Exn.result
    19   datatype node_edit =
    19   datatype node_edit =
    20     Remove |
    20     Clear |
    21     Edits of (command_id option * command_id option) list |
    21     Edits of (command_id option * command_id option) list |
    22     Header of node_header
    22     Header of node_header
    23   type edit = string * node_edit
    23   type edit = string * node_edit
    24   type state
    24   type state
    25   val init_state: state
    25   val init_state: state
    53 
    53 
    54 
    54 
    55 
    55 
    56 (** document structure **)
    56 (** document structure **)
    57 
    57 
    58 type node_header = (string * string list * string list) Exn.result;
    58 type node_header = (string * string list * (string * bool) list) Exn.result;
    59 structure Entries = Linear_Set(type key = command_id val ord = int_ord);
    59 structure Entries = Linear_Set(type key = command_id val ord = int_ord);
    60 
    60 
    61 abstype node = Node of
    61 abstype node = Node of
    62  {header: node_header,
    62  {header: node_header,
    63   entries: exec_id option Entries.T,  (*command entries with excecutions*)
    63   entries: exec_id option Entries.T,  (*command entries with excecutions*)
    80 
    80 
    81 fun get_last (Node {last, ...}) = last;
    81 fun get_last (Node {last, ...}) = last;
    82 fun set_last last = map_node (fn (header, entries, _) => (header, entries, last));
    82 fun set_last last = map_node (fn (header, entries, _) => (header, entries, last));
    83 
    83 
    84 val empty_node = make_node (Exn.Exn (ERROR "Bad theory header"), Entries.empty, no_id);
    84 val empty_node = make_node (Exn.Exn (ERROR "Bad theory header"), Entries.empty, no_id);
    85 val empty_version = Version Graph.empty;
    85 val clear_node = map_node (fn (header, _, _) => (header, Entries.empty, no_id));
       
    86 
       
    87 fun get_node nodes name = Graph.get_node nodes name handle Graph.UNDEF _ => empty_node;
       
    88 fun remove_node name nodes = Graph.del_node name nodes handle Graph.UNDEF _ => nodes;
       
    89 fun update_node name f = Graph.default_node (name, empty_node) #> Graph.map_node name f;
    86 
    90 
    87 
    91 
    88 (* node edits and associated executions *)
    92 (* node edits and associated executions *)
    89 
    93 
    90 datatype node_edit =
    94 datatype node_edit =
    91   Remove |
    95   Clear |
    92   Edits of (command_id option * command_id option) list |
    96   Edits of (command_id option * command_id option) list |
    93   Header of node_header;
    97   Header of node_header;
    94 
    98 
    95 type edit = string * node_edit;
    99 type edit = string * node_edit;
    96 
   100 
   112     | (id, NONE) => Entries.delete_after id #> reset_after id);
   116     | (id, NONE) => Entries.delete_after id #> reset_after id);
   113 
   117 
   114 
   118 
   115 (* version operations *)
   119 (* version operations *)
   116 
   120 
       
   121 val empty_version = Version Graph.empty;
       
   122 
   117 fun nodes_of (Version nodes) = nodes;
   123 fun nodes_of (Version nodes) = nodes;
       
   124 val node_of = get_node o nodes_of;
   118 val node_names_of = Graph.keys o nodes_of;
   125 val node_names_of = Graph.keys o nodes_of;
   119 
   126 
   120 fun get_node version name = Graph.get_node (nodes_of version) name
   127 fun cycle_msg names = "Cyclic dependency of " ^ space_implode " via " (map quote names);
   121   handle Graph.UNDEF _ => empty_node;
       
   122 
       
   123 fun update_node name f =
       
   124   Graph.default_node (name, empty_node) #> Graph.map_node name f;
       
   125 
   128 
   126 fun edit_nodes (name, node_edit) (Version nodes) =
   129 fun edit_nodes (name, node_edit) (Version nodes) =
   127   Version
   130   Version
   128     (case node_edit of
   131     (case node_edit of
   129       Remove => perhaps (try (Graph.del_node name)) nodes
   132       Clear => update_node name clear_node nodes
   130     | Edits edits => update_node name (edit_node edits) nodes
   133     | Edits edits => update_node name (edit_node edits) nodes
   131     (* FIXME maintain deps; cycles!? *)
   134     | Header header =>
   132     | Header header => update_node name (set_header header) nodes);
   135         let
       
   136           val node = get_node nodes name;
       
   137           val nodes' = Graph.new_node (name, node) (remove_node name nodes);
       
   138           val parents =
       
   139             (case header of Exn.Res (_, parents, _) => parents | _ => [])
       
   140             |> filter (can (Graph.get_node nodes'));
       
   141           val (header', nodes'') =
       
   142             (header, Graph.add_deps_acyclic (name, parents) nodes')
       
   143               handle Graph.CYCLES cs => (Exn.Exn (ERROR (cat_lines (map cycle_msg cs))), nodes');
       
   144         in Graph.map_node name (set_header header') nodes'' end);
   133 
   145 
   134 fun put_node name node (Version nodes) =
   146 fun put_node name node (Version nodes) =
   135   Version (nodes
   147   Version (nodes
   136     |> Graph.default_node (name, empty_node)
   148     |> Graph.default_node (name, empty_node)
   137     |> Graph.map_node name (K node));
   149     |> Graph.map_node name (K node));
   212     NONE => err_undef "command execution" id
   224     NONE => err_undef "command execution" id
   213   | SOME exec => exec);
   225   | SOME exec => exec);
   214 
   226 
   215 fun get_theory state version_id pos name =
   227 fun get_theory state version_id pos name =
   216   let
   228   let
   217     val last = get_last (get_node (the_version state version_id) name);
   229     val last = get_last (node_of (the_version state version_id) name);
   218     val st =
   230     val st =
   219       (case Lazy.peek (the_exec state last) of
   231       (case Lazy.peek (the_exec state last) of
   220         SOME result => #2 (Exn.release result)
   232         SOME result => #2 (Exn.release result)
   221       | NONE => error ("Unfinished execution for theory " ^ quote name));
   233       | NONE => error ("Unfinished execution for theory " ^ quote name ^ Position.str_of pos));
   222   in Toplevel.end_theory pos st end;
   234   in Toplevel.end_theory pos st end;
   223 
   235 
   224 
   236 
   225 (* document execution *)
   237 (* document execution *)
   226 
   238 
   261       | errs => (errs, NONE))
   273       | errs => (errs, NONE))
   262   | NONE => ([ML_Compiler.exn_message Runtime.TERMINATE], NONE));
   274   | NONE => ([ML_Compiler.exn_message Runtime.TERMINATE], NONE));
   263 
   275 
   264 in
   276 in
   265 
   277 
   266 fun run_command node_name raw_tr st =
   278 fun run_command (node_name, node_header) raw_tr st =
   267   (case
   279   let
   268       (case Toplevel.init_of raw_tr of
   280     val is_init = Toplevel.is_init raw_tr;
   269         SOME _ =>
   281     val tr =
   270           Exn.capture (fn () =>
   282       if is_init then
   271             let val master_dir = Path.dir (Path.explode node_name);  (* FIXME move to Scala side *)
   283         raw_tr |> Toplevel.modify_init (fn _ =>
   272             in Toplevel.modify_master (SOME master_dir) raw_tr end) ()
   284           let
   273       | NONE => Exn.Res raw_tr) of
   285             (* FIXME get theories from document state *)
   274     Exn.Res tr =>
   286             (* FIXME provide files via Scala layer *)
   275       let
   287             val (name, imports, uses) = Exn.release node_header;
   276         val is_init = is_some (Toplevel.init_of tr);
   288             val master = SOME (Path.dir (Path.explode node_name));
   277         val is_proof = Keyword.is_proof (Toplevel.name_of tr);
   289           in Thy_Info.toplevel_begin_theory master name imports (map (apfst Path.explode) uses) end)
   278         val do_print = not is_init andalso (Toplevel.print_of tr orelse is_proof);
   290       else raw_tr;
   279 
   291 
   280         val start = Timing.start ();
   292     val is_proof = Keyword.is_proof (Toplevel.name_of tr);
   281         val (errs, result) =
   293     val do_print = not is_init andalso (Toplevel.print_of tr orelse is_proof);
   282           if Toplevel.is_toplevel st andalso not is_init then ([], SOME st)
   294 
   283           else run (is_init orelse is_proof) (Toplevel.set_print false tr) st;
   295     val start = Timing.start ();
   284         val _ = timing tr (Timing.result start);
   296     val (errs, result) =
   285         val _ = List.app (Toplevel.error_msg tr) errs;
   297       if Toplevel.is_toplevel st andalso not is_init then ([], SOME st)
   286         val res =
   298       else run (is_init orelse is_proof) (Toplevel.set_print false tr) st;
   287           (case result of
   299     val _ = timing tr (Timing.result start);
   288             NONE => (Toplevel.status tr Markup.failed; (false, st))
   300     val _ = List.app (Toplevel.error_msg tr) errs;
   289           | SOME st' =>
   301   in
   290              (Toplevel.status tr Markup.finished;
   302     (case result of
   291               proof_status tr st';
   303       NONE => (Toplevel.status tr Markup.failed; (false, st))
   292               if do_print then async_state tr st' else ();
   304     | SOME st' =>
   293               (true, st')));
   305        (Toplevel.status tr Markup.finished;
   294       in res end
   306         proof_status tr st';
   295   | Exn.Exn exn =>
   307         if do_print then async_state tr st' else ();
   296       if Exn.is_interrupt exn then reraise exn
   308         (true, st')))
   297       else
   309   end;
   298        (Toplevel.error_msg raw_tr (ML_Compiler.exn_message exn);
       
   299         Toplevel.status raw_tr Markup.failed;
       
   300         (false, Toplevel.toplevel)));
       
   301 
   310 
   302 end;
   311 end;
   303 
   312 
   304 
   313 
   305 
   314 
   313 fun is_changed node' ((_, id), exec) =
   322 fun is_changed node' ((_, id), exec) =
   314   (case try (the_entry node') id of
   323   (case try (the_entry node') id of
   315     NONE => true
   324     NONE => true
   316   | SOME exec' => exec' <> exec);
   325   | SOME exec' => exec' <> exec);
   317 
   326 
   318 fun new_exec name (id: command_id) (exec_id, updates, state) =
   327 fun new_exec node_info (id: command_id) (exec_id, updates, state) =
   319   let
   328   let
   320     val exec = the_exec state exec_id;
   329     val exec = the_exec state exec_id;
   321     val exec_id' = new_id ();
   330     val exec_id' = new_id ();
   322     val future_tr = the_command state id;
   331     val future_tr = the_command state id;
   323     val exec' =
   332     val exec' =
   324       Lazy.lazy (fn () =>
   333       Lazy.lazy (fn () =>
   325         let
   334         let
   326           val st = #2 (Lazy.force exec);
   335           val st = #2 (Lazy.force exec);
   327           val exec_tr = Toplevel.put_id (print_id exec_id') (Future.join future_tr);
   336           val exec_tr = Toplevel.put_id (print_id exec_id') (Future.join future_tr);
   328         in run_command name exec_tr st end);
   337         in run_command node_info exec_tr st end);
   329     val state' = define_exec exec_id' exec' state;
   338     val state' = define_exec exec_id' exec' state;
   330   in (exec_id', (id, exec_id') :: updates, state') end;
   339   in (exec_id', (id, exec_id') :: updates, state') end;
   331 
   340 
   332 in
   341 in
   333 
   342 
   336     val old_version = the_version state old_id;
   345     val old_version = the_version state old_id;
   337     val _ = Time.now ();  (* FIXME odd workaround for polyml-5.4.0/x86_64 *)
   346     val _ = Time.now ();  (* FIXME odd workaround for polyml-5.4.0/x86_64 *)
   338     val new_version = fold edit_nodes edits old_version;
   347     val new_version = fold edit_nodes edits old_version;
   339 
   348 
   340     fun update_node name (rev_updates, version, st) =
   349     fun update_node name (rev_updates, version, st) =
   341       let val node = get_node version name in
   350       let
   342         (case first_entry NONE (is_changed (get_node old_version name)) node of
   351         val node = node_of version name;
       
   352         val header = get_header node;
       
   353       in
       
   354         (case first_entry NONE (is_changed (node_of old_version name)) node of
   343           NONE => (rev_updates, version, st)
   355           NONE => (rev_updates, version, st)
   344         | SOME ((prev, id), _) =>
   356         | SOME ((prev, id), _) =>
   345             let
   357             let
   346               val prev_exec =
   358               val prev_exec =
   347                 (case prev of
   359                 (case prev of
   348                   NONE => no_id
   360                   NONE => no_id
   349                 | SOME prev_id => the_default no_id (the_entry node prev_id));
   361                 | SOME prev_id => the_default no_id (the_entry node prev_id));
   350               val (last, rev_upds, st') =
   362               val (last, rev_upds, st') =
   351                 fold_entries (SOME id) (new_exec name o #2 o #1) node (prev_exec, [], st);
   363                 fold_entries (SOME id) (new_exec (name, header) o #2 o #1) node (prev_exec, [], st);
   352               val node' = node |> fold update_entry rev_upds |> set_last last;
   364               val node' = node |> fold update_entry rev_upds |> set_last last;
   353             in (rev_upds @ rev_updates, put_node name node' version, st') end)
   365             in (rev_upds @ rev_updates, put_node name node' version, st') end)
   354       end;
   366       end;
   355 
   367 
   356     (* FIXME proper node deps *)
   368     (* FIXME Graph.schedule *)
   357     val (rev_updates, new_version', state') =
   369     val (rev_updates, new_version', state') =
   358       fold update_node (node_names_of new_version) ([], new_version, state);
   370       fold update_node (node_names_of new_version) ([], new_version, state);
   359     val state'' = define_version new_id new_version' state';
   371     val state'' = define_version new_id new_version' state';
   360 
   372 
   361     val _ = join_commands state'';  (* FIXME async!? *)
   373     val _ = join_commands state'';  (* FIXME async!? *)
   378         Future.forks
   390         Future.forks
   379           {name = "Document.execute", group = NONE, deps = [], pri = 1, interrupts = true}
   391           {name = "Document.execute", group = NONE, deps = [], pri = 1, interrupts = true}
   380           [fn () =>
   392           [fn () =>
   381             node_names_of version |> List.app (fn name =>
   393             node_names_of version |> List.app (fn name =>
   382               fold_entries NONE (fn (_, exec) => fn () => force_exec exec)
   394               fold_entries NONE (fn (_, exec) => fn () => force_exec exec)
   383                   (get_node version name) ())];
   395                   (node_of version name) ())];
   384 
   396 
   385     in (versions, commands, execs, execution') end);
   397     in (versions, commands, execs, execution') end);
   386 
   398 
   387 
   399 
   388 
   400