383 } |
383 } |
384 |
384 |
385 def purge_suppressed: Option[Nodes] = |
385 def purge_suppressed: Option[Nodes] = |
386 graph.keys_iterator.filter(is_suppressed).toList match { |
386 graph.keys_iterator.filter(is_suppressed).toList match { |
387 case Nil => None |
387 case Nil => None |
388 case del => Some(new Nodes((graph /: del)(_.del_node(_)))) |
388 case del => Some(new Nodes(del.foldLeft(graph)(_.del_node(_)))) |
389 } |
389 } |
390 |
390 |
391 def + (entry: (Node.Name, Node)): Nodes = |
391 def + (entry: (Node.Name, Node)): Nodes = |
392 { |
392 { |
393 val (name, node) = entry |
393 val (name, node) = entry |
394 val imports = node.header.imports |
394 val imports = node.header.imports |
395 val graph1 = |
395 val graph1 = |
396 (graph.default_node(name, Node.empty) /: imports)((g, p) => g.default_node(p, Node.empty)) |
396 imports.foldLeft(graph.default_node(name, Node.empty)) { |
397 val graph2 = (graph1 /: graph1.imm_preds(name))((g, dep) => g.del_edge(dep, name)) |
397 case (g, p) => g.default_node(p, Node.empty) |
398 val graph3 = (graph2 /: imports)((g, dep) => g.add_edge(dep, name)) |
398 } |
|
399 val graph2 = |
|
400 graph1.imm_preds(name).foldLeft(graph1) { case (g, dep) => g.del_edge(dep, name) } |
|
401 val graph3 = imports.foldLeft(graph2) { case (g, dep) => g.add_edge(dep, name) } |
399 new Nodes(graph3.map_node(name, _ => node)) |
402 new Nodes(graph3.map_node(name, _ => node)) |
400 } |
403 } |
401 |
404 |
402 def domain: Set[Node.Name] = graph.domain |
405 def domain: Set[Node.Name] = graph.domain |
403 |
406 |
447 } |
450 } |
448 |
451 |
449 def purge_suppressed( |
452 def purge_suppressed( |
450 versions: Map[Document_ID.Version, Version]): Map[Document_ID.Version, Version] = |
453 versions: Map[Document_ID.Version, Version]): Map[Document_ID.Version, Version] = |
451 { |
454 { |
452 (versions /: |
455 (for ((id, v) <- versions.iterator; v1 <- v.purge_suppressed) yield (id, v1)). |
453 (for ((id, v) <- versions.iterator; v1 <- v.purge_suppressed) yield (id, v1)))(_ + _) |
456 foldLeft(versions)(_ + _) |
454 } |
457 } |
455 } |
458 } |
456 |
459 |
457 final class Version private( |
460 final class Version private( |
458 val id: Document_ID.Version = Document_ID.none, |
461 val id: Document_ID.Version = Document_ID.none, |
565 def is_outdated: Boolean = edits.nonEmpty |
568 def is_outdated: Boolean = edits.nonEmpty |
566 |
569 |
567 private lazy val reverse_edits = edits.reverse |
570 private lazy val reverse_edits = edits.reverse |
568 |
571 |
569 def convert(offset: Text.Offset): Text.Offset = |
572 def convert(offset: Text.Offset): Text.Offset = |
570 (offset /: edits)((i, edit) => edit.convert(i)) |
573 edits.foldLeft(offset) { case (i, edit) => edit.convert(i) } |
571 def revert(offset: Text.Offset): Text.Offset = |
574 def revert(offset: Text.Offset): Text.Offset = |
572 (offset /: reverse_edits)((i, edit) => edit.revert(i)) |
575 reverse_edits.foldLeft(offset) { case (i, edit) => edit.revert(i) } |
573 |
576 |
574 def convert(range: Text.Range): Text.Range = range.map(convert) |
577 def convert(range: Text.Range): Text.Range = range.map(convert) |
575 def revert(range: Text.Range): Text.Range = range.map(revert) |
578 def revert(range: Text.Range): Text.Range = range.map(revert) |
576 |
579 |
577 |
580 |
681 val name = command.node_name.node |
684 val name = command.node_name.node |
682 val sources_iterator = |
685 val sources_iterator = |
683 node.commands.iterator.takeWhile(_ != command).map(_.source) ++ |
686 node.commands.iterator.takeWhile(_ != command).map(_.source) ++ |
684 (if (offset == 0) Iterator.empty |
687 (if (offset == 0) Iterator.empty |
685 else Iterator.single(command.source(Text.Range(0, command.chunk.decode(offset))))) |
688 else Iterator.single(command.source(Text.Range(0, command.chunk.decode(offset))))) |
686 val pos = (Line.Position.zero /: sources_iterator)(_.advance(_)) |
689 val pos = sources_iterator.foldLeft(Line.Position.zero)(_.advance(_)) |
687 Line.Node_Position(name, pos) |
690 Line.Node_Position(name, pos) |
688 } |
691 } |
689 |
692 |
690 def current_command(other_node_name: Node.Name, offset: Text.Offset): Option[Command] = |
693 def current_command(other_node_name: Node.Name, offset: Text.Offset): Option[Command] = |
691 if (other_node_name.is_theory) { |
694 if (other_node_name.is_theory) { |
840 |
843 |
841 def assign(update: Assign_Update): Assignment = |
844 def assign(update: Assign_Update): Assignment = |
842 { |
845 { |
843 require(!is_finished, "assignment already finished") |
846 require(!is_finished, "assignment already finished") |
844 val command_execs1 = |
847 val command_execs1 = |
845 (command_execs /: update) { |
848 update.foldLeft(command_execs) { |
846 case (res, (command_id, exec_ids)) => |
849 case (res, (command_id, exec_ids)) => |
847 if (exec_ids.isEmpty) res - command_id |
850 if (exec_ids.isEmpty) res - command_id |
848 else res + (command_id -> exec_ids) |
851 else res + (command_id -> exec_ids) |
849 } |
852 } |
850 new Assignment(command_execs1, true) |
853 new Assignment(command_execs1, true) |
926 if st.command.node_name == node_name |
929 if st.command.node_name == node_name |
927 } yield (Symbol.Text_Chunk.Id(st.command.id), st.command.chunk) |
930 } yield (Symbol.Text_Chunk.Id(st.command.id), st.command.chunk) |
928 } |
931 } |
929 |
932 |
930 private def redirection(st: Command.State): Graph[Document_ID.Command, Unit] = |
933 private def redirection(st: Command.State): Graph[Document_ID.Command, Unit] = |
931 (commands_redirection /: st.markups.redirection_iterator)({ case (graph, id) => |
934 st.markups.redirection_iterator.foldLeft(commands_redirection) { |
932 graph.default_node(id, ()).default_node(st.command.id, ()).add_edge(id, st.command.id) }) |
935 case (graph, id) => |
|
936 graph.default_node(id, ()).default_node(st.command.id, ()).add_edge(id, st.command.id) |
|
937 } |
933 |
938 |
934 def accumulate(id: Document_ID.Generic, message: XML.Elem, cache: XML.Cache) |
939 def accumulate(id: Document_ID.Generic, message: XML.Elem, cache: XML.Cache) |
935 : (Command.State, State) = |
940 : (Command.State, State) = |
936 { |
941 { |
937 def update(st: Command.State): (Command.State, State) = |
942 def update(st: Command.State): (Command.State, State) = |
1020 def upd(exec_id: Document_ID.Exec, st: Command.State) |
1025 def upd(exec_id: Document_ID.Exec, st: Command.State) |
1021 : Option[(Document_ID.Exec, Command.State)] = |
1026 : Option[(Document_ID.Exec, Command.State)] = |
1022 if (execs.isDefinedAt(exec_id)) None else Some(exec_id -> st) |
1027 if (execs.isDefinedAt(exec_id)) None else Some(exec_id -> st) |
1023 |
1028 |
1024 val (changed_commands, new_execs) = |
1029 val (changed_commands, new_execs) = |
1025 ((Nil: List[Command], execs) /: update) { |
1030 update.foldLeft((Nil: List[Command], execs)) { |
1026 case ((commands1, execs1), (command_id, exec)) => |
1031 case ((commands1, execs1), (command_id, exec)) => |
1027 val st = the_static_state(command_id) |
1032 val st = the_static_state(command_id) |
1028 val command = st.command |
1033 val command = st.command |
1029 val commands2 = command :: commands1 |
1034 val commands2 = command :: commands1 |
1030 val execs2 = |
1035 val execs2 = |
1248 (name, edits) <- change.rev_edits |
1253 (name, edits) <- change.rev_edits |
1249 if name == node_name |
1254 if name == node_name |
1250 } yield edits |
1255 } yield edits |
1251 |
1256 |
1252 val edits = |
1257 val edits = |
1253 (pending_edits /: rev_pending_changes)({ |
1258 rev_pending_changes.foldLeft(pending_edits) { |
1254 case (edits, Node.Edits(es)) => es ::: edits |
1259 case (edits, Node.Edits(es)) => es ::: edits |
1255 case (edits, _) => edits |
1260 case (edits, _) => edits |
1256 }) |
1261 } |
1257 |
1262 |
1258 new Snapshot(this, version, node_name, edits, snippet_command) |
1263 new Snapshot(this, version, node_name, edits, snippet_command) |
1259 } |
1264 } |
1260 |
1265 |
1261 def snippet(command: Command): Snapshot = |
1266 def snippet(command: Command): Snapshot = |