src/Pure/PIDE/document.scala
changeset 52530 99dd8b4ef3fe
parent 52527 dbac84eab3bc
child 52531 21f8e0e151f5
equal deleted inserted replaced
52528:b6a224676c04 52530:99dd8b4ef3fe
    11 import scala.collection.mutable
    11 import scala.collection.mutable
    12 
    12 
    13 
    13 
    14 object Document
    14 object Document
    15 {
    15 {
    16   /* formal identifiers */
       
    17 
       
    18   type ID = Long
       
    19   val ID = Properties.Value.Long
       
    20 
       
    21   type Version_ID = ID
       
    22   type Command_ID = ID
       
    23   type Exec_ID = ID
       
    24 
       
    25   val no_id: ID = 0
       
    26   val new_id = Counter()
       
    27 
       
    28 
       
    29 
       
    30   /** document structure **/
    16   /** document structure **/
    31 
    17 
    32   /* individual nodes */
    18   /* individual nodes */
    33 
    19 
    34   type Edit[A, B] = (Node.Name, Node.Edit[A, B])
    20   type Edit[A, B] = (Node.Name, Node.Edit[A, B])
   200   object Version
   186   object Version
   201   {
   187   {
   202     val init: Version = new Version()
   188     val init: Version = new Version()
   203 
   189 
   204     def make(syntax: Outer_Syntax, nodes: Nodes): Version =
   190     def make(syntax: Outer_Syntax, nodes: Nodes): Version =
   205       new Version(new_id(), syntax, nodes)
   191       new Version(Document_ID.make(), syntax, nodes)
   206   }
   192   }
   207 
   193 
   208   final class Version private(
   194   final class Version private(
   209     val id: Version_ID = no_id,
   195     val id: Document_ID.Version = Document_ID.none,
   210     val syntax: Outer_Syntax = Outer_Syntax.empty,
   196     val syntax: Outer_Syntax = Outer_Syntax.empty,
   211     val nodes: Nodes = Nodes.empty)
   197     val nodes: Nodes = Nodes.empty)
   212   {
   198   {
   213     def is_init: Boolean = id == no_id
   199     def is_init: Boolean = id == Document_ID.none
   214   }
   200   }
   215 
   201 
   216 
   202 
   217   /* changes of plain text, eventually resulting in document edits */
   203   /* changes of plain text, eventually resulting in document edits */
   218 
   204 
   287       range: Text.Range,
   273       range: Text.Range,
   288       elements: Option[Set[String]],
   274       elements: Option[Set[String]],
   289       result: Command.State => PartialFunction[Text.Markup, A]): Stream[Text.Info[A]]
   275       result: Command.State => PartialFunction[Text.Markup, A]): Stream[Text.Info[A]]
   290   }
   276   }
   291 
   277 
   292   type Assign = List[(Document.Command_ID, List[Document.Exec_ID])]  // exec state assignment
   278   type Assign = List[(Document_ID.Command, List[Document_ID.Exec])]  // exec state assignment
   293 
   279 
   294   object State
   280   object State
   295   {
   281   {
   296     class Fail(state: State) extends Exception
   282     class Fail(state: State) extends Exception
   297 
   283 
   299     {
   285     {
   300       val init: Assignment = new Assignment()
   286       val init: Assignment = new Assignment()
   301     }
   287     }
   302 
   288 
   303     final class Assignment private(
   289     final class Assignment private(
   304       val command_execs: Map[Command_ID, List[Exec_ID]] = Map.empty,
   290       val command_execs: Map[Document_ID.Command, List[Document_ID.Exec]] = Map.empty,
   305       val is_finished: Boolean = false)
   291       val is_finished: Boolean = false)
   306     {
   292     {
   307       def check_finished: Assignment = { require(is_finished); this }
   293       def check_finished: Assignment = { require(is_finished); this }
   308       def unfinished: Assignment = new Assignment(command_execs, false)
   294       def unfinished: Assignment = new Assignment(command_execs, false)
   309 
   295 
   310       def assign(add_command_execs: List[(Command_ID, List[Exec_ID])]): Assignment =
   296       def assign(
       
   297         add_command_execs: List[(Document_ID.Command, List[Document_ID.Exec])]): Assignment =
   311       {
   298       {
   312         require(!is_finished)
   299         require(!is_finished)
   313         val command_execs1 =
   300         val command_execs1 =
   314           (command_execs /: add_command_execs) {
   301           (command_execs /: add_command_execs) {
   315             case (res, (command_id, Nil)) => res - command_id
   302             case (res, (command_id, Nil)) => res - command_id
   322     val init: State =
   309     val init: State =
   323       State().define_version(Version.init, Assignment.init).assign(Version.init.id)._2
   310       State().define_version(Version.init, Assignment.init).assign(Version.init.id)._2
   324   }
   311   }
   325 
   312 
   326   final case class State private(
   313   final case class State private(
   327     val versions: Map[Version_ID, Version] = Map.empty,
   314     val versions: Map[Document_ID.Version, Version] = Map.empty,
   328     val commands: Map[Command_ID, Command.State] = Map.empty,  // static markup from define_command
   315     val commands: Map[Document_ID.Command, Command.State] = Map.empty,  // static markup from define_command
   329     val execs: Map[Exec_ID, Command.State] = Map.empty,  // dynamic markup from execution
   316     val execs: Map[Document_ID.Exec, Command.State] = Map.empty,  // dynamic markup from execution
   330     val assignments: Map[Version_ID, State.Assignment] = Map.empty,
   317     val assignments: Map[Document_ID.Version, State.Assignment] = Map.empty,
   331     val history: History = History.init)
   318     val history: History = History.init)
   332   {
   319   {
   333     private def fail[A]: A = throw new State.Fail(this)
   320     private def fail[A]: A = throw new State.Fail(this)
   334 
   321 
   335     def define_version(version: Version, assignment: State.Assignment): State =
   322     def define_version(version: Version, assignment: State.Assignment): State =
   343     {
   330     {
   344       val id = command.id
   331       val id = command.id
   345       copy(commands = commands + (id -> command.init_state))
   332       copy(commands = commands + (id -> command.init_state))
   346     }
   333     }
   347 
   334 
   348     def defined_command(id: Command_ID): Boolean = commands.isDefinedAt(id)
   335     def defined_command(id: Document_ID.Command): Boolean = commands.isDefinedAt(id)
   349 
   336 
   350     def find_command(version: Version, id: ID): Option[(Node, Command)] =
   337     def find_command(version: Version, id: Document_ID.ID): Option[(Node, Command)] =
   351       commands.get(id) orElse execs.get(id) match {
   338       commands.get(id) orElse execs.get(id) match {
   352         case None => None
   339         case None => None
   353         case Some(st) =>
   340         case Some(st) =>
   354           val command = st.command
   341           val command = st.command
   355           val node = version.nodes(command.node_name)
   342           val node = version.nodes(command.node_name)
   356           Some((node, command))
   343           Some((node, command))
   357       }
   344       }
   358 
   345 
   359     def the_version(id: Version_ID): Version = versions.getOrElse(id, fail)
   346     def the_version(id: Document_ID.Version): Version = versions.getOrElse(id, fail)
   360     def the_read_state(id: Command_ID): Command.State = commands.getOrElse(id, fail)
   347     def the_read_state(id: Document_ID.Command): Command.State = commands.getOrElse(id, fail)
   361     def the_exec_state(id: Exec_ID): Command.State = execs.getOrElse(id, fail)
   348     def the_exec_state(id: Document_ID.Exec): Command.State = execs.getOrElse(id, fail)
   362     def the_assignment(version: Version): State.Assignment =
   349     def the_assignment(version: Version): State.Assignment =
   363       assignments.getOrElse(version.id, fail)
   350       assignments.getOrElse(version.id, fail)
   364 
   351 
   365     def accumulate(id: ID, message: XML.Elem): (Command.State, State) =
   352     def accumulate(id: Document_ID.ID, message: XML.Elem): (Command.State, State) =
   366       execs.get(id) match {
   353       execs.get(id) match {
   367         case Some(st) =>
   354         case Some(st) =>
   368           val new_st = st + (id, message)
   355           val new_st = st + (id, message)
   369           (new_st, copy(execs = execs + (id -> new_st)))
   356           (new_st, copy(execs = execs + (id -> new_st)))
   370         case None =>
   357         case None =>
   374               (new_st, copy(commands = commands + (id -> new_st)))
   361               (new_st, copy(commands = commands + (id -> new_st)))
   375             case None => fail
   362             case None => fail
   376           }
   363           }
   377       }
   364       }
   378 
   365 
   379     def assign(id: Version_ID, command_execs: Assign = Nil): (List[Command], State) =
   366     def assign(id: Document_ID.Version, command_execs: Assign = Nil): (List[Command], State) =
   380     {
   367     {
   381       val version = the_version(id)
   368       val version = the_version(id)
   382 
   369 
   383       val (changed_commands, new_execs) =
   370       val (changed_commands, new_execs) =
   384         ((Nil: List[Command], execs) /: command_execs) {
   371         ((Nil: List[Command], execs) /: command_execs) {
   435           (dropped_versions, state1)
   422           (dropped_versions, state1)
   436         case None => fail
   423         case None => fail
   437       }
   424       }
   438     }
   425     }
   439 
   426 
   440     def removed_versions(removed: List[Version_ID]): State =
   427     def removed_versions(removed: List[Document_ID.Version]): State =
   441     {
   428     {
   442       val versions1 = versions -- removed
   429       val versions1 = versions -- removed
   443       val assignments1 = assignments -- removed
   430       val assignments1 = assignments -- removed
   444       var commands1 = Map.empty[Command_ID, Command.State]
   431       var commands1 = Map.empty[Document_ID.Command, Command.State]
   445       var execs1 = Map.empty[Exec_ID, Command.State]
   432       var execs1 = Map.empty[Document_ID.Exec, Command.State]
   446       for {
   433       for {
   447         (version_id, version) <- versions1.iterator
   434         (version_id, version) <- versions1.iterator
   448         command_execs = assignments1(version_id).command_execs
   435         command_execs = assignments1(version_id).command_execs
   449         (_, node) <- version.nodes.entries
   436         (_, node) <- version.nodes.entries
   450         command <- node.commands.iterator
   437         command <- node.commands.iterator