src/Pure/PIDE/document.scala
author wenzelm
Wed, 11 Aug 2010 22:41:26 +0200
changeset 38355 8cb265fb12fe
parent 38227 6bbb42843b6e
child 38356 443fb83a21e8
permissions -rw-r--r--
represent document ids by (long) int, to benefit from the somewhat faster Inttab in ML (LinearSet in Scala is invariably indexed by native object ids);
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
36676
ac7961d42ac3 some rearrangement of Scala sources;
wenzelm
parents: 36012
diff changeset
     1
/*  Title:      Pure/PIDE/document.scala
ac7961d42ac3 some rearrangement of Scala sources;
wenzelm
parents: 36012
diff changeset
     2
    Author:     Makarius
ac7961d42ac3 some rearrangement of Scala sources;
wenzelm
parents: 36012
diff changeset
     3
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
     4
Document as collection of named nodes, each consisting of an editable
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
     5
list of commands.
36676
ac7961d42ac3 some rearrangement of Scala sources;
wenzelm
parents: 36012
diff changeset
     6
*/
34407
aad6834ba380 added some headers and comments;
wenzelm
parents: 34390
diff changeset
     7
34871
e596a0b71f3c incorporate "proofdocument" part into main Isabelle/Pure.jar -- except for html_panel.scala, which depends on external library (Lobo/Cobra browser);
wenzelm
parents: 34868
diff changeset
     8
package isabelle
34318
c13e168a8ae6 original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
wenzelm
parents:
diff changeset
     9
34760
dc7f5e0d9d27 misc modernization of names;
wenzelm
parents: 34759
diff changeset
    10
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
    11
import scala.collection.mutable
37073
5e42e36a6693 @tailrec annotation;
wenzelm
parents: 37072
diff changeset
    12
import scala.annotation.tailrec
5e42e36a6693 @tailrec annotation;
wenzelm
parents: 37072
diff changeset
    13
5e42e36a6693 @tailrec annotation;
wenzelm
parents: 37072
diff changeset
    14
34823
2f3ea37c5958 renamed Proof_Document to Document;
wenzelm
parents: 34819
diff changeset
    15
object Document
34483
0923926022d7 superficial tuning;
wenzelm
parents: 34482
diff changeset
    16
{
38227
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    17
  /* formal identifiers */
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
    18
38355
8cb265fb12fe represent document ids by (long) int, to benefit from the somewhat faster Inttab in ML (LinearSet in Scala is invariably indexed by native object ids);
wenzelm
parents: 38227
diff changeset
    19
  type Version_ID = Long
8cb265fb12fe represent document ids by (long) int, to benefit from the somewhat faster Inttab in ML (LinearSet in Scala is invariably indexed by native object ids);
wenzelm
parents: 38227
diff changeset
    20
  type Command_ID = Long
8cb265fb12fe represent document ids by (long) int, to benefit from the somewhat faster Inttab in ML (LinearSet in Scala is invariably indexed by native object ids);
wenzelm
parents: 38227
diff changeset
    21
  type State_ID = Long
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
    22
38355
8cb265fb12fe represent document ids by (long) int, to benefit from the somewhat faster Inttab in ML (LinearSet in Scala is invariably indexed by native object ids);
wenzelm
parents: 38227
diff changeset
    23
  val NO_ID = 0L
8cb265fb12fe represent document ids by (long) int, to benefit from the somewhat faster Inttab in ML (LinearSet in Scala is invariably indexed by native object ids);
wenzelm
parents: 38227
diff changeset
    24
8cb265fb12fe represent document ids by (long) int, to benefit from the somewhat faster Inttab in ML (LinearSet in Scala is invariably indexed by native object ids);
wenzelm
parents: 38227
diff changeset
    25
  def parse_id(s: String): Long = java.lang.Long.parseLong(s)
8cb265fb12fe represent document ids by (long) int, to benefit from the somewhat faster Inttab in ML (LinearSet in Scala is invariably indexed by native object ids);
wenzelm
parents: 38227
diff changeset
    26
  def print_id(id: Long): String = id.toString
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
    27
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
    28
34818
7df68a8f0e3e register Proof_Document instances as session entities -- handle Markup.EDIT messages locally;
wenzelm
parents: 34815
diff changeset
    29
38227
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    30
  /** named document nodes **/
38151
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    31
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    32
  object Node
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    33
  {
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    34
    val empty: Node = new Node(Linear_Set())
38227
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    35
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    36
    def command_starts(commands: Iterator[Command], offset: Int = 0): Iterator[(Command, Int)] =
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    37
    {
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    38
      var i = offset
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    39
      for (command <- commands) yield {
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    40
        val start = i
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    41
        i += command.length
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    42
        (command, start)
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    43
      }
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    44
    }
38151
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    45
  }
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    46
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    47
  class Node(val commands: Linear_Set[Command])
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    48
  {
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    49
    /* command ranges */
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    50
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    51
    def command_starts: Iterator[(Command, Int)] =
38227
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    52
      Node.command_starts(commands.iterator)
38151
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    53
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    54
    def command_start(cmd: Command): Option[Int] =
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    55
      command_starts.find(_._1 == cmd).map(_._2)
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    56
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    57
    def command_range(i: Int): Iterator[(Command, Int)] =
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    58
      command_starts dropWhile { case (cmd, start) => start + cmd.length <= i }
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    59
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    60
    def command_range(i: Int, j: Int): Iterator[(Command, Int)] =
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    61
      command_range(i) takeWhile { case (_, start) => start < j }
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    62
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    63
    def command_at(i: Int): Option[(Command, Int)] =
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    64
    {
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    65
      val range = command_range(i)
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    66
      if (range.hasNext) Some(range.next) else None
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    67
    }
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    68
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    69
    def proper_command_at(i: Int): Option[Command] =
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    70
      command_at(i) match {
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    71
        case Some((command, _)) =>
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    72
          commands.reverse_iterator(command).find(cmd => !cmd.is_ignored)
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    73
        case None => None
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    74
      }
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    75
  }
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    76
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    77
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
    78
  /* initial document */
34485
6475bfb4ff99 joined Document with ProofDocument;
wenzelm
parents: 34483
diff changeset
    79
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
    80
  val init: Document =
34835
67733fd0e3fa back to explicit management of documents -- not as generic Session.Entity -- to avoid ill-defined referencing of new states;
wenzelm
parents: 34832
diff changeset
    81
  {
38151
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    82
    val doc = new Document(NO_ID, Map().withDefaultValue(Node.empty), Map())
34835
67733fd0e3fa back to explicit management of documents -- not as generic Session.Entity -- to avoid ill-defined referencing of new states;
wenzelm
parents: 34832
diff changeset
    83
    doc.assign_states(Nil)
67733fd0e3fa back to explicit management of documents -- not as generic Session.Entity -- to avoid ill-defined referencing of new states;
wenzelm
parents: 34832
diff changeset
    84
    doc
67733fd0e3fa back to explicit management of documents -- not as generic Session.Entity -- to avoid ill-defined referencing of new states;
wenzelm
parents: 34832
diff changeset
    85
  }
34660
e0561943bfc9 Change consisting of a list of Edits
immler@in.tum.de
parents: 34657
diff changeset
    86
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
    87
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
    88
38227
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    89
  /** changes of plain text, eventually resulting in document edits **/
38151
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    90
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    91
  type Node_Text_Edit = (String, List[Text_Edit])  // FIXME None: remove
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    92
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    93
  type Edit[C] =
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    94
   (String,  // node name
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
    95
    Option[List[(Option[C], Option[C])]])  // None: remove, Some: insert/remove commands
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
    96
38227
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    97
  abstract class Snapshot
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    98
  {
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
    99
    val document: Document
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   100
    val node: Document.Node
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   101
    val is_outdated: Boolean
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   102
    def convert(offset: Int): Int
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   103
    def revert(offset: Int): Int
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   104
  }
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   105
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   106
  object Change
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   107
  {
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   108
    val init = new Change(NO_ID, None, Nil, Future.value(Nil, Document.init))
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   109
  }
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   110
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   111
  class Change(
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   112
    val id: Version_ID,
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   113
    val parent: Option[Change],
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   114
    val edits: List[Node_Text_Edit],
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   115
    val result: Future[(List[Edit[Command]], Document)])
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   116
  {
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   117
    def ancestors: Iterator[Change] = new Iterator[Change]
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   118
    {
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   119
      private var state: Option[Change] = Some(Change.this)
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   120
      def hasNext = state.isDefined
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   121
      def next =
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   122
        state match {
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   123
          case Some(change) => state = change.parent; change
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   124
          case None => throw new NoSuchElementException("next on empty iterator")
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   125
        }
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   126
    }
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   127
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   128
    def join_document: Document = result.join._2
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   129
    def is_assigned: Boolean = result.is_finished && join_document.assignment.is_finished
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   130
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   131
    def snapshot(name: String, pending_edits: List[Text_Edit]): Snapshot =
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   132
    {
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   133
      val latest = Change.this
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   134
      val stable = latest.ancestors.find(_.is_assigned)
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   135
      require(stable.isDefined)
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   136
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   137
      val edits =
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   138
        (pending_edits /: latest.ancestors.takeWhile(_ != stable.get))((edits, change) =>
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   139
            (for ((a, eds) <- change.edits if a == name) yield eds).flatten ::: edits)
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   140
      lazy val reverse_edits = edits.reverse
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   141
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   142
      new Snapshot {
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   143
        val document = stable.get.join_document
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   144
        val node = document.nodes(name)
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   145
        val is_outdated = !(pending_edits.isEmpty && latest == stable.get)
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   146
        def convert(offset: Int): Int = (offset /: edits)((i, edit) => edit.convert(i))
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   147
        def revert(offset: Int): Int = (offset /: reverse_edits)((i, edit) => edit.revert(i))
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   148
      }
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   149
    }
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   150
  }
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   151
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   152
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   153
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   154
  /** editing **/
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   155
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   156
  def text_edits(session: Session, old_doc: Document, new_id: Version_ID,
38151
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
   157
      edits: List[Node_Text_Edit]): (List[Edit[Command]], Document) =
34824
ac35eee85f5c renamed current_document to recent_document (might be a bit older than current_change);
wenzelm
parents: 34823
diff changeset
   158
  {
34840
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   159
    require(old_doc.assignment.is_finished)
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   160
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   161
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   162
    /* unparsed dummy commands */
34538
20bfcca24658 Prover as actor managing ProofDocument-versions (removed EventBus structural_changes);
immler@in.tum.de
parents: 34532
diff changeset
   163
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   164
    def unparsed(source: String) =
38220
b30aa2dbedca avoid null in Scala;
wenzelm
parents: 38151
diff changeset
   165
      new Command(NO_ID, List(Token(Token.Kind.UNPARSED, source)))
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   166
38220
b30aa2dbedca avoid null in Scala;
wenzelm
parents: 38151
diff changeset
   167
    def is_unparsed(command: Command) = command.id == NO_ID
34835
67733fd0e3fa back to explicit management of documents -- not as generic Session.Entity -- to avoid ill-defined referencing of new states;
wenzelm
parents: 34832
diff changeset
   168
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   169
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   170
    /* phase 1: edit individual command source */
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   171
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   172
    @tailrec def edit_text(eds: List[Text_Edit],
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   173
        commands: Linear_Set[Command]): Linear_Set[Command] =
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   174
    {
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   175
      eds match {
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   176
        case e :: es =>
38227
6bbb42843b6e concentrate structural document notions in document.scala;
wenzelm
parents: 38220
diff changeset
   177
          Node.command_starts(commands.iterator).find {
34866
a4fe43df58b3 new unparsed span for text right after existing command;
wenzelm
parents: 34863
diff changeset
   178
            case (cmd, cmd_start) =>
37685
305c326db33b more efficient document model/view -- avoid repeated iteration over commands from start, prefer bulk operations;
wenzelm
parents: 37186
diff changeset
   179
              e.can_edit(cmd.source, cmd_start) ||
305c326db33b more efficient document model/view -- avoid repeated iteration over commands from start, prefer bulk operations;
wenzelm
parents: 37186
diff changeset
   180
                e.is_insert && e.start == cmd_start + cmd.length
34863
3e655d0ff936 eliminated strange mutable var commands;
wenzelm
parents: 34862
diff changeset
   181
          } match {
34866
a4fe43df58b3 new unparsed span for text right after existing command;
wenzelm
parents: 34863
diff changeset
   182
            case Some((cmd, cmd_start)) if e.can_edit(cmd.source, cmd_start) =>
a4fe43df58b3 new unparsed span for text right after existing command;
wenzelm
parents: 34863
diff changeset
   183
              val (rest, text) = e.edit(cmd.source, cmd_start)
a4fe43df58b3 new unparsed span for text right after existing command;
wenzelm
parents: 34863
diff changeset
   184
              val new_commands = commands.insert_after(Some(cmd), unparsed(text)) - cmd
34863
3e655d0ff936 eliminated strange mutable var commands;
wenzelm
parents: 34862
diff changeset
   185
              edit_text(rest.toList ::: es, new_commands)
34318
c13e168a8ae6 original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
wenzelm
parents:
diff changeset
   186
34866
a4fe43df58b3 new unparsed span for text right after existing command;
wenzelm
parents: 34863
diff changeset
   187
            case Some((cmd, cmd_start)) =>
a4fe43df58b3 new unparsed span for text right after existing command;
wenzelm
parents: 34863
diff changeset
   188
              edit_text(es, commands.insert_after(Some(cmd), unparsed(e.text)))
a4fe43df58b3 new unparsed span for text right after existing command;
wenzelm
parents: 34863
diff changeset
   189
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   190
            case None =>
34866
a4fe43df58b3 new unparsed span for text right after existing command;
wenzelm
parents: 34863
diff changeset
   191
              require(e.is_insert && e.start == 0)
34863
3e655d0ff936 eliminated strange mutable var commands;
wenzelm
parents: 34862
diff changeset
   192
              edit_text(es, commands.insert_after(None, unparsed(e.text)))
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   193
          }
34863
3e655d0ff936 eliminated strange mutable var commands;
wenzelm
parents: 34862
diff changeset
   194
        case Nil => commands
34318
c13e168a8ae6 original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
wenzelm
parents:
diff changeset
   195
      }
c13e168a8ae6 original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
wenzelm
parents:
diff changeset
   196
    }
34582
5d5d253c7c29 superficial tuning;
wenzelm
parents: 34575
diff changeset
   197
34818
7df68a8f0e3e register Proof_Document instances as session entities -- handle Markup.EDIT messages locally;
wenzelm
parents: 34815
diff changeset
   198
34866
a4fe43df58b3 new unparsed span for text right after existing command;
wenzelm
parents: 34863
diff changeset
   199
    /* phase 2: recover command spans */
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   200
37073
5e42e36a6693 @tailrec annotation;
wenzelm
parents: 37072
diff changeset
   201
    @tailrec def parse_spans(commands: Linear_Set[Command]): Linear_Set[Command] =
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   202
    {
36011
3ff725ac13a4 adapted to Scala 2.8.0 Beta1 -- with notable changes to scala.collection;
wenzelm
parents: 34871
diff changeset
   203
      commands.iterator.find(is_unparsed) match {
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   204
        case Some(first_unparsed) =>
37071
dd3540a489f7 parse_spans: cover full range including adjacent well-formed commands -- intermediate ignored and malformed commands are reparsed as well;
wenzelm
parents: 37059
diff changeset
   205
          val first =
37072
9105c8237c7a renamed "rev" to "reverse" following usual Scala conventions;
wenzelm
parents: 37071
diff changeset
   206
            commands.reverse_iterator(first_unparsed).find(_.is_command) getOrElse commands.head
37071
dd3540a489f7 parse_spans: cover full range including adjacent well-formed commands -- intermediate ignored and malformed commands are reparsed as well;
wenzelm
parents: 37059
diff changeset
   207
          val last =
dd3540a489f7 parse_spans: cover full range including adjacent well-formed commands -- intermediate ignored and malformed commands are reparsed as well;
wenzelm
parents: 37059
diff changeset
   208
            commands.iterator(first_unparsed).find(_.is_command) getOrElse commands.last
dd3540a489f7 parse_spans: cover full range including adjacent well-formed commands -- intermediate ignored and malformed commands are reparsed as well;
wenzelm
parents: 37059
diff changeset
   209
          val range =
dd3540a489f7 parse_spans: cover full range including adjacent well-formed commands -- intermediate ignored and malformed commands are reparsed as well;
wenzelm
parents: 37059
diff changeset
   210
            commands.iterator(first).takeWhile(_ != last).toList ::: List(last)
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   211
37071
dd3540a489f7 parse_spans: cover full range including adjacent well-formed commands -- intermediate ignored and malformed commands are reparsed as well;
wenzelm
parents: 37059
diff changeset
   212
          val sources = range.flatMap(_.span.map(_.source))
34866
a4fe43df58b3 new unparsed span for text right after existing command;
wenzelm
parents: 34863
diff changeset
   213
          val spans0 = Thy_Syntax.parse_spans(session.current_syntax.scan(sources.mkString))
34485
6475bfb4ff99 joined Document with ProofDocument;
wenzelm
parents: 34483
diff changeset
   214
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   215
          val (before_edit, spans1) =
37071
dd3540a489f7 parse_spans: cover full range including adjacent well-formed commands -- intermediate ignored and malformed commands are reparsed as well;
wenzelm
parents: 37059
diff changeset
   216
            if (!spans0.isEmpty && first.is_command && first.span == spans0.head)
dd3540a489f7 parse_spans: cover full range including adjacent well-formed commands -- intermediate ignored and malformed commands are reparsed as well;
wenzelm
parents: 37059
diff changeset
   217
              (Some(first), spans0.tail)
dd3540a489f7 parse_spans: cover full range including adjacent well-formed commands -- intermediate ignored and malformed commands are reparsed as well;
wenzelm
parents: 37059
diff changeset
   218
            else (commands.prev(first), spans0)
34544
56217d219e27 proofdocument-versions get id from changes
immler@in.tum.de
parents: 34541
diff changeset
   219
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   220
          val (after_edit, spans2) =
37071
dd3540a489f7 parse_spans: cover full range including adjacent well-formed commands -- intermediate ignored and malformed commands are reparsed as well;
wenzelm
parents: 37059
diff changeset
   221
            if (!spans1.isEmpty && last.is_command && last.span == spans1.last)
dd3540a489f7 parse_spans: cover full range including adjacent well-formed commands -- intermediate ignored and malformed commands are reparsed as well;
wenzelm
parents: 37059
diff changeset
   222
              (Some(last), spans1.take(spans1.length - 1))
dd3540a489f7 parse_spans: cover full range including adjacent well-formed commands -- intermediate ignored and malformed commands are reparsed as well;
wenzelm
parents: 37059
diff changeset
   223
            else (commands.next(last), spans1)
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   224
34863
3e655d0ff936 eliminated strange mutable var commands;
wenzelm
parents: 34862
diff changeset
   225
          val inserted = spans2.map(span => new Command(session.create_id(), span))
3e655d0ff936 eliminated strange mutable var commands;
wenzelm
parents: 34862
diff changeset
   226
          val new_commands =
3e655d0ff936 eliminated strange mutable var commands;
wenzelm
parents: 34862
diff changeset
   227
            commands.delete_between(before_edit, after_edit).append_after(before_edit, inserted)
34866
a4fe43df58b3 new unparsed span for text right after existing command;
wenzelm
parents: 34863
diff changeset
   228
          parse_spans(new_commands)
34485
6475bfb4ff99 joined Document with ProofDocument;
wenzelm
parents: 34483
diff changeset
   229
34863
3e655d0ff936 eliminated strange mutable var commands;
wenzelm
parents: 34862
diff changeset
   230
        case None => commands
34485
6475bfb4ff99 joined Document with ProofDocument;
wenzelm
parents: 34483
diff changeset
   231
      }
6475bfb4ff99 joined Document with ProofDocument;
wenzelm
parents: 34483
diff changeset
   232
    }
34739
34b0aadab7ee Linear_Set.append_after;
wenzelm
parents: 34724
diff changeset
   233
34554
7dc6c231da40 abs. stops, markup nodes depend on doc-version;
immler@in.tum.de
parents: 34551
diff changeset
   234
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   235
    /* phase 3: resulting document edits */
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   236
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   237
    {
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   238
      val doc_edits = new mutable.ListBuffer[Edit[Command]]
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   239
      var nodes = old_doc.nodes
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   240
      var former_states = old_doc.assignment.join
34660
e0561943bfc9 Change consisting of a list of Edits
immler@in.tum.de
parents: 34657
diff changeset
   241
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   242
      for ((name, text_edits) <- edits) {
38151
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
   243
        val commands0 = nodes(name).commands
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   244
        val commands1 = edit_text(text_edits, commands0)
38220
b30aa2dbedca avoid null in Scala;
wenzelm
parents: 38151
diff changeset
   245
        val commands2 = parse_spans(commands1)   // FIXME somewhat slow
34863
3e655d0ff936 eliminated strange mutable var commands;
wenzelm
parents: 34862
diff changeset
   246
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   247
        val removed_commands = commands0.iterator.filter(!commands2.contains(_)).toList
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   248
        val inserted_commands = commands2.iterator.filter(!commands0.contains(_)).toList
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   249
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   250
        val cmd_edits =
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   251
          removed_commands.reverse.map(cmd => (commands0.prev(cmd), None)) :::
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   252
          inserted_commands.map(cmd => (commands2.prev(cmd), Some(cmd)))
34660
e0561943bfc9 Change consisting of a list of Edits
immler@in.tum.de
parents: 34657
diff changeset
   253
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   254
        doc_edits += (name -> Some(cmd_edits))
38151
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
   255
        nodes += (name -> new Node(commands2))
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   256
        former_states --= removed_commands
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   257
      }
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   258
      (doc_edits.toList, new Document(new_id, nodes, former_states))
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   259
    }
34485
6475bfb4ff99 joined Document with ProofDocument;
wenzelm
parents: 34483
diff changeset
   260
  }
34840
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   261
}
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   262
34855
81d0410dc3ac iterators for ranges of commands/starts -- avoid extra array per document;
wenzelm
parents: 34853
diff changeset
   263
34840
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   264
class Document(
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   265
    val id: Document.Version_ID,
38151
2837c952ca31 explicit Change.Snapshot and Document.Node;
wenzelm
parents: 38150
diff changeset
   266
    val nodes: Map[String, Document.Node],
38150
67fc24df3721 simplified/refined document model: collection of named nodes, without proper dependencies yet;
wenzelm
parents: 37849
diff changeset
   267
    former_states: Map[Command, Command])  // FIXME !?
34840
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   268
{
34855
81d0410dc3ac iterators for ranges of commands/starts -- avoid extra array per document;
wenzelm
parents: 34853
diff changeset
   269
  /* command state assignment */
34840
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   270
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   271
  val assignment = Future.promise[Map[Command, Command]]
34853
32b49207ca20 misc tuning and clarification of Document/Change;
wenzelm
parents: 34840
diff changeset
   272
  def await_assignment { assignment.join }
34840
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   273
34859
f986d84dd44b renamed Command.content to source;
wenzelm
parents: 34855
diff changeset
   274
  @volatile private var tmp_states = former_states
34840
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   275
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   276
  def assign_states(new_states: List[(Command, Command)])
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   277
  {
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   278
    assignment.fulfill(tmp_states ++ new_states)
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   279
    tmp_states = Map()
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   280
  }
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   281
36990
449628c148cf explicit Command.Status.UNDEFINED -- avoid fragile/cumbersome treatment of Option[State];
wenzelm
parents: 36956
diff changeset
   282
  def current_state(cmd: Command): State =
34840
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   283
  {
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   284
    require(assignment.is_finished)
36990
449628c148cf explicit Command.Status.UNDEFINED -- avoid fragile/cumbersome treatment of Option[State];
wenzelm
parents: 36956
diff changeset
   285
    (assignment.join).get(cmd) match {
449628c148cf explicit Command.Status.UNDEFINED -- avoid fragile/cumbersome treatment of Option[State];
wenzelm
parents: 36956
diff changeset
   286
      case Some(cmd_state) => cmd_state.current_state
37186
349e9223c685 explicit markup for forked goals, as indicated by Goal.fork;
wenzelm
parents: 37073
diff changeset
   287
      case None => new State(cmd, Command.Status.UNDEFINED, 0, Nil, cmd.empty_markup)
36990
449628c148cf explicit Command.Status.UNDEFINED -- avoid fragile/cumbersome treatment of Option[State];
wenzelm
parents: 36956
diff changeset
   288
    }
34840
6c5560d48561 more precise treatment of document/state assigment;
wenzelm
parents: 34838
diff changeset
   289
  }
34318
c13e168a8ae6 original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
wenzelm
parents:
diff changeset
   290
}