| author | desharna | 
| Mon, 19 Dec 2022 08:37:03 +0100 | |
| changeset 76692 | 98880b2430ea | 
| parent 75659 | 9bd92ac9328f | 
| child 76975 | 5ba8cb258e75 | 
| permissions | -rw-r--r-- | 
| 
38479
 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 
wenzelm 
parents: 
38478 
diff
changeset
 | 
1  | 
/* Title: Pure/PIDE/markup_tree.scala  | 
| 36676 | 2  | 
Author: Fabian Immler, TU Munich  | 
3  | 
Author: Makarius  | 
|
4  | 
||
| 
38479
 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 
wenzelm 
parents: 
38478 
diff
changeset
 | 
5  | 
Markup trees over nested / non-overlapping text ranges.  | 
| 36676 | 6  | 
*/  | 
| 34393 | 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: 
34760 
diff
changeset
 | 
8  | 
package isabelle  | 
| 34393 | 9  | 
|
| 
34701
 
80b0add08eef
IsabelleSideKickParser: incorporate former MarkupNode.markup2default_node, observe stopped flag;
 
wenzelm 
parents: 
34676 
diff
changeset
 | 
10  | 
|
| 
38479
 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 
wenzelm 
parents: 
38478 
diff
changeset
 | 
11  | 
import scala.collection.immutable.SortedMap  | 
| 49614 | 12  | 
import scala.collection.mutable  | 
| 49467 | 13  | 
import scala.annotation.tailrec  | 
| 
38479
 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 
wenzelm 
parents: 
38478 
diff
changeset
 | 
14  | 
|
| 
 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 
wenzelm 
parents: 
38478 
diff
changeset
 | 
15  | 
|
| 75393 | 16  | 
object Markup_Tree {
 | 
| 50551 | 17  | 
/* construct trees */  | 
18  | 
||
| 45456 | 19  | 
val empty: Markup_Tree = new Markup_Tree(Branches.empty)  | 
| 
38479
 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 
wenzelm 
parents: 
38478 
diff
changeset
 | 
20  | 
|
| 56743 | 21  | 
def merge(trees: List[Markup_Tree], range: Text.Range, elements: Markup.Elements): Markup_Tree =  | 
| 73359 | 22  | 
trees.foldLeft(empty)(_.merge(_, range, elements))  | 
| 
56299
 
8201790fdeb9
more careful treatment of multiple command states (eval + prints): merge content that is actually required;
 
wenzelm 
parents: 
55820 
diff
changeset
 | 
23  | 
|
| 49467 | 24  | 
def merge_disjoint(trees: List[Markup_Tree]): Markup_Tree =  | 
25  | 
    trees match {
 | 
|
26  | 
case Nil => empty  | 
|
27  | 
case head :: tail =>  | 
|
28  | 
new Markup_Tree(  | 
|
| 73359 | 29  | 
          tail.foldLeft(head.branches) {
 | 
| 49467 | 30  | 
case (branches, tree) =>  | 
| 73359 | 31  | 
              tree.branches.foldLeft(branches) {
 | 
| 49467 | 32  | 
case (bs, (r, entry)) =>  | 
| 
73120
 
c3589f2dff31
more informative errors: simplify diagnosis of spurious failures reported by users;
 
wenzelm 
parents: 
72815 
diff
changeset
 | 
33  | 
require(!bs.isDefinedAt(r), "cannot merge markup trees")  | 
| 49467 | 34  | 
bs + (r -> entry)  | 
35  | 
}  | 
|
36  | 
})  | 
|
37  | 
}  | 
|
38  | 
||
| 50551 | 39  | 
|
40  | 
/* tree building blocks */  | 
|
41  | 
||
| 75393 | 42  | 
  object Entry {
 | 
| 45473 | 43  | 
def apply(markup: Text.Markup, subtree: Markup_Tree): Entry =  | 
| 
55652
 
33ad12ef79ff
eliminated somewhat pointless elements index (see also f793dd5d84b2, 2b7fed8c9c4ac): less memory and more speed (avoid linear "exists" of 19dffae33cde);
 
wenzelm 
parents: 
55645 
diff
changeset
 | 
44  | 
Entry(markup.range, List(markup.info), subtree)  | 
| 45473 | 45  | 
}  | 
46  | 
||
| 
45474
 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 
wenzelm 
parents: 
45473 
diff
changeset
 | 
47  | 
sealed case class Entry(  | 
| 
 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 
wenzelm 
parents: 
45473 
diff
changeset
 | 
48  | 
range: Text.Range,  | 
| 
 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 
wenzelm 
parents: 
45473 
diff
changeset
 | 
49  | 
rev_markup: List[XML.Elem],  | 
| 75393 | 50  | 
subtree: Markup_Tree  | 
51  | 
  ) {
 | 
|
| 
50552
 
2b7fd8c9c4ac
maintain subtree_elements for improved performance of cumulate operator;
 
wenzelm 
parents: 
50551 
diff
changeset
 | 
52  | 
def markup: List[XML.Elem] = rev_markup.reverse  | 
| 
45474
 
f793dd5d84b2
index markup elements for more efficient cumulate/select operations;
 
wenzelm 
parents: 
45473 
diff
changeset
 | 
53  | 
|
| 75393 | 54  | 
    def filter_markup(elements: Markup.Elements): List[XML.Elem] = {
 | 
| 
55645
 
561754277494
tuned -- remaining rev_markup is rather short after filter;
 
wenzelm 
parents: 
55622 
diff
changeset
 | 
55  | 
var result: List[XML.Elem] = Nil  | 
| 60215 | 56  | 
for (elem <- rev_markup if elements(elem.name))  | 
| 
55645
 
561754277494
tuned -- remaining rev_markup is rather short after filter;
 
wenzelm 
parents: 
55622 
diff
changeset
 | 
57  | 
result ::= elem  | 
| 72815 | 58  | 
result  | 
| 
55645
 
561754277494
tuned -- remaining rev_markup is rather short after filter;
 
wenzelm 
parents: 
55622 
diff
changeset
 | 
59  | 
}  | 
| 
 
561754277494
tuned -- remaining rev_markup is rather short after filter;
 
wenzelm 
parents: 
55622 
diff
changeset
 | 
60  | 
|
| 
55652
 
33ad12ef79ff
eliminated somewhat pointless elements index (see also f793dd5d84b2, 2b7fed8c9c4ac): less memory and more speed (avoid linear "exists" of 19dffae33cde);
 
wenzelm 
parents: 
55645 
diff
changeset
 | 
61  | 
def + (markup: Text.Markup): Entry = copy(rev_markup = markup.info :: rev_markup)  | 
| 
 
33ad12ef79ff
eliminated somewhat pointless elements index (see also f793dd5d84b2, 2b7fed8c9c4ac): less memory and more speed (avoid linear "exists" of 19dffae33cde);
 
wenzelm 
parents: 
55645 
diff
changeset
 | 
62  | 
def \ (markup: Text.Markup): Entry = copy(subtree = subtree + markup)  | 
| 
45469
 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 
wenzelm 
parents: 
45468 
diff
changeset
 | 
63  | 
}  | 
| 
 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 
wenzelm 
parents: 
45468 
diff
changeset
 | 
64  | 
|
| 75393 | 65  | 
  object Branches {
 | 
| 38578 | 66  | 
type T = SortedMap[Text.Range, Entry]  | 
| 45456 | 67  | 
val empty: T = SortedMap.empty(Text.Range.Ordering)  | 
| 
38479
 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 
wenzelm 
parents: 
38478 
diff
changeset
 | 
68  | 
}  | 
| 49466 | 69  | 
|
70  | 
||
71  | 
/* XML representation */  | 
|
72  | 
||
| 
49650
 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 
wenzelm 
parents: 
49614 
diff
changeset
 | 
73  | 
@tailrec private def strip_elems(  | 
| 
 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 
wenzelm 
parents: 
49614 
diff
changeset
 | 
74  | 
elems: List[XML.Elem], body: XML.Body): (List[XML.Elem], XML.Body) =  | 
| 49467 | 75  | 
    body match {
 | 
| 
49650
 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 
wenzelm 
parents: 
49614 
diff
changeset
 | 
76  | 
case List(XML.Wrapped_Elem(markup1, body1, body2)) =>  | 
| 
 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 
wenzelm 
parents: 
49614 
diff
changeset
 | 
77  | 
strip_elems(XML.Elem(markup1, body1) :: elems, body2)  | 
| 
 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 
wenzelm 
parents: 
49614 
diff
changeset
 | 
78  | 
case List(XML.Elem(markup1, body1)) =>  | 
| 
 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 
wenzelm 
parents: 
49614 
diff
changeset
 | 
79  | 
strip_elems(XML.Elem(markup1, Nil) :: elems, body1)  | 
| 
 
9fad6480300d
support for wrapped XML elements, which allows to preserve full markup tree information in to_XML/from_XML conversion;
 
wenzelm 
parents: 
49614 
diff
changeset
 | 
80  | 
case _ => (elems, body)  | 
| 49467 | 81  | 
}  | 
82  | 
||
| 75393 | 83  | 
private def make_trees(  | 
84  | 
acc: (Int, List[Markup_Tree]),  | 
|
85  | 
tree: XML.Tree  | 
|
86  | 
  ): (Int, List[Markup_Tree]) = {
 | 
|
87  | 
val (offset, markup_trees) = acc  | 
|
| 49467 | 88  | 
|
| 75393 | 89  | 
    strip_elems(Nil, List(tree)) match {
 | 
90  | 
case (Nil, body) =>  | 
|
91  | 
(offset + XML.text_length(body), markup_trees)  | 
|
| 49466 | 92  | 
|
| 75393 | 93  | 
case (elems, body) =>  | 
94  | 
val (end_offset, subtrees) =  | 
|
95  | 
body.foldLeft((offset, List.empty[Markup_Tree]))(make_trees)  | 
|
96  | 
if (offset == end_offset) acc  | 
|
97  | 
        else {
 | 
|
98  | 
val range = Text.Range(offset, end_offset)  | 
|
99  | 
val entry = Entry(range, elems, merge_disjoint(subtrees))  | 
|
100  | 
(end_offset, new Markup_Tree(Branches.empty, entry) :: markup_trees)  | 
|
101  | 
}  | 
|
| 49467 | 102  | 
}  | 
| 75393 | 103  | 
}  | 
| 49466 | 104  | 
|
| 49467 | 105  | 
def from_XML(body: XML.Body): Markup_Tree =  | 
| 73361 | 106  | 
merge_disjoint(body.foldLeft((0, List.empty[Markup_Tree]))(make_trees)._2)  | 
| 
38479
 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 
wenzelm 
parents: 
38478 
diff
changeset
 | 
107  | 
}  | 
| 
34554
 
7dc6c231da40
abs. stops, markup nodes depend on doc-version;
 
immler@in.tum.de 
parents: 
34517 
diff
changeset
 | 
108  | 
|
| 34393 | 109  | 
|
| 75393 | 110  | 
final class Markup_Tree private(val branches: Markup_Tree.Branches.T) {
 | 
| 49417 | 111  | 
import Markup_Tree._  | 
112  | 
||
| 
45469
 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 
wenzelm 
parents: 
45468 
diff
changeset
 | 
113  | 
private def this(branches: Markup_Tree.Branches.T, entry: Markup_Tree.Entry) =  | 
| 
 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 
wenzelm 
parents: 
45468 
diff
changeset
 | 
114  | 
this(branches + (entry.range -> entry))  | 
| 
 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 
wenzelm 
parents: 
45468 
diff
changeset
 | 
115  | 
|
| 
 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 
wenzelm 
parents: 
45468 
diff
changeset
 | 
116  | 
private def overlapping(range: Text.Range): Branches.T =  | 
| 56311 | 117  | 
if (branches.isEmpty ||  | 
| 56313 | 118  | 
(range.contains(branches.firstKey.start) && branches.lastKey.stop <= range.stop))  | 
| 56311 | 119  | 
branches  | 
120  | 
    else {
 | 
|
121  | 
val start = Text.Range(range.start)  | 
|
122  | 
val stop = Text.Range(range.stop)  | 
|
123  | 
val bs = branches.range(start, stop)  | 
|
124  | 
      branches.get(stop) match {
 | 
|
125  | 
case Some(end) if range overlaps end.range => bs + (end.range -> end)  | 
|
126  | 
case _ => bs  | 
|
127  | 
}  | 
|
| 45457 | 128  | 
}  | 
129  | 
||
| 
56307
 
2bdf8261677a
more frugal merge of markup trees: restrict to expected range before checking trivial cases, e.g. relevant for sporadic warnings (eval_exec) within big ML reports (print_exec);
 
wenzelm 
parents: 
56302 
diff
changeset
 | 
130  | 
def restrict(range: Text.Range): Markup_Tree =  | 
| 
 
2bdf8261677a
more frugal merge of markup trees: restrict to expected range before checking trivial cases, e.g. relevant for sporadic warnings (eval_exec) within big ML reports (print_exec);
 
wenzelm 
parents: 
56302 
diff
changeset
 | 
131  | 
new Markup_Tree(overlapping(range))  | 
| 
 
2bdf8261677a
more frugal merge of markup trees: restrict to expected range before checking trivial cases, e.g. relevant for sporadic warnings (eval_exec) within big ML reports (print_exec);
 
wenzelm 
parents: 
56302 
diff
changeset
 | 
132  | 
|
| 
 
2bdf8261677a
more frugal merge of markup trees: restrict to expected range before checking trivial cases, e.g. relevant for sporadic warnings (eval_exec) within big ML reports (print_exec);
 
wenzelm 
parents: 
56302 
diff
changeset
 | 
133  | 
def is_empty: Boolean = branches.isEmpty  | 
| 
 
2bdf8261677a
more frugal merge of markup trees: restrict to expected range before checking trivial cases, e.g. relevant for sporadic warnings (eval_exec) within big ML reports (print_exec);
 
wenzelm 
parents: 
56302 
diff
changeset
 | 
134  | 
|
| 75393 | 135  | 
  def + (new_markup: Text.Markup): Markup_Tree = {
 | 
| 
45469
 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 
wenzelm 
parents: 
45468 
diff
changeset
 | 
136  | 
val new_range = new_markup.range  | 
| 
 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 
wenzelm 
parents: 
45468 
diff
changeset
 | 
137  | 
|
| 38578 | 138  | 
    branches.get(new_range) match {
 | 
| 45473 | 139  | 
case None => new Markup_Tree(branches, Entry(new_markup, empty))  | 
| 
45469
 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 
wenzelm 
parents: 
45468 
diff
changeset
 | 
140  | 
case Some(entry) =>  | 
| 
 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 
wenzelm 
parents: 
45468 
diff
changeset
 | 
141  | 
if (entry.range == new_range)  | 
| 
50552
 
2b7fd8c9c4ac
maintain subtree_elements for improved performance of cumulate operator;
 
wenzelm 
parents: 
50551 
diff
changeset
 | 
142  | 
new Markup_Tree(branches, entry + new_markup)  | 
| 
45469
 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 
wenzelm 
parents: 
45468 
diff
changeset
 | 
143  | 
else if (entry.range.contains(new_range))  | 
| 
50552
 
2b7fd8c9c4ac
maintain subtree_elements for improved performance of cumulate operator;
 
wenzelm 
parents: 
50551 
diff
changeset
 | 
144  | 
new Markup_Tree(branches, entry \ new_markup)  | 
| 38578 | 145  | 
else if (new_range.contains(branches.head._1) && new_range.contains(branches.last._1))  | 
| 45473 | 146  | 
new Markup_Tree(Branches.empty, Entry(new_markup, this))  | 
| 
38482
 
7b6ee937b75f
tuned Markup_Tree, using SortedMap more carefully;
 
wenzelm 
parents: 
38479 
diff
changeset
 | 
147  | 
        else {
 | 
| 45457 | 148  | 
val body = overlapping(new_range)  | 
| 
49607
 
b610c0d52bfa
updated to consolidated SortedMap in scala-2.9.x;
 
wenzelm 
parents: 
49469 
diff
changeset
 | 
149  | 
if (body.forall(e => new_range.contains(e._1)))  | 
| 
 
b610c0d52bfa
updated to consolidated SortedMap in scala-2.9.x;
 
wenzelm 
parents: 
49469 
diff
changeset
 | 
150  | 
new Markup_Tree(branches -- body.keys, Entry(new_markup, new Markup_Tree(body)))  | 
| 49608 | 151  | 
          else {
 | 
| 58463 | 152  | 
            Output.warning("Ignored overlapping markup information: " + new_markup + "\n" +
 | 
| 71383 | 153  | 
              body.filter(e => !new_range.contains(e._1)).values.mkString("\n"))
 | 
| 
38482
 
7b6ee937b75f
tuned Markup_Tree, using SortedMap more carefully;
 
wenzelm 
parents: 
38479 
diff
changeset
 | 
154  | 
this  | 
| 
 
7b6ee937b75f
tuned Markup_Tree, using SortedMap more carefully;
 
wenzelm 
parents: 
38479 
diff
changeset
 | 
155  | 
}  | 
| 
 
7b6ee937b75f
tuned Markup_Tree, using SortedMap more carefully;
 
wenzelm 
parents: 
38479 
diff
changeset
 | 
156  | 
}  | 
| 34703 | 157  | 
}  | 
158  | 
}  | 
|
159  | 
||
| 75393 | 160  | 
  def merge(other: Markup_Tree, root_range: Text.Range, elements: Markup.Elements): Markup_Tree = {
 | 
| 
56301
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
161  | 
def merge_trees(tree1: Markup_Tree, tree2: Markup_Tree): Markup_Tree =  | 
| 73359 | 162  | 
      tree2.branches.foldLeft(tree1) {
 | 
163  | 
case (tree, (range, entry)) =>  | 
|
164  | 
if (!range.overlaps(root_range)) tree  | 
|
165  | 
          else {
 | 
|
166  | 
            entry.filter_markup(elements).foldLeft(merge_trees(tree, entry.subtree)) {
 | 
|
167  | 
case (t, elem) => t + Text.Info(range, elem)  | 
|
168  | 
}  | 
|
169  | 
}  | 
|
170  | 
}  | 
|
| 49614 | 171  | 
|
| 
56307
 
2bdf8261677a
more frugal merge of markup trees: restrict to expected range before checking trivial cases, e.g. relevant for sporadic warnings (eval_exec) within big ML reports (print_exec);
 
wenzelm 
parents: 
56302 
diff
changeset
 | 
172  | 
if (this eq other) this  | 
| 
 
2bdf8261677a
more frugal merge of markup trees: restrict to expected range before checking trivial cases, e.g. relevant for sporadic warnings (eval_exec) within big ML reports (print_exec);
 
wenzelm 
parents: 
56302 
diff
changeset
 | 
173  | 
    else {
 | 
| 
 
2bdf8261677a
more frugal merge of markup trees: restrict to expected range before checking trivial cases, e.g. relevant for sporadic warnings (eval_exec) within big ML reports (print_exec);
 
wenzelm 
parents: 
56302 
diff
changeset
 | 
174  | 
val tree1 = this.restrict(root_range)  | 
| 
 
2bdf8261677a
more frugal merge of markup trees: restrict to expected range before checking trivial cases, e.g. relevant for sporadic warnings (eval_exec) within big ML reports (print_exec);
 
wenzelm 
parents: 
56302 
diff
changeset
 | 
175  | 
val tree2 = other.restrict(root_range)  | 
| 
 
2bdf8261677a
more frugal merge of markup trees: restrict to expected range before checking trivial cases, e.g. relevant for sporadic warnings (eval_exec) within big ML reports (print_exec);
 
wenzelm 
parents: 
56302 
diff
changeset
 | 
176  | 
if (tree1.is_empty) tree2  | 
| 
 
2bdf8261677a
more frugal merge of markup trees: restrict to expected range before checking trivial cases, e.g. relevant for sporadic warnings (eval_exec) within big ML reports (print_exec);
 
wenzelm 
parents: 
56302 
diff
changeset
 | 
177  | 
else merge_trees(tree1, tree2)  | 
| 
 
2bdf8261677a
more frugal merge of markup trees: restrict to expected range before checking trivial cases, e.g. relevant for sporadic warnings (eval_exec) within big ML reports (print_exec);
 
wenzelm 
parents: 
56302 
diff
changeset
 | 
178  | 
}  | 
| 49614 | 179  | 
}  | 
180  | 
||
| 75393 | 181  | 
def cumulate[A](  | 
182  | 
root_range: Text.Range,  | 
|
183  | 
root_info: A,  | 
|
184  | 
elements: Markup.Elements,  | 
|
185  | 
result: (A, Text.Markup) => Option[A]  | 
|
186  | 
  ): List[Text.Info[A]] = {
 | 
|
187  | 
    def results(x: A, entry: Entry): Option[A] = {
 | 
|
| 
52889
 
ea3338812e67
more tight interface for markup cumulate/select: avoid duplicate application, allow to defer decision about definedness;
 
wenzelm 
parents: 
52642 
diff
changeset
 | 
188  | 
var y = x  | 
| 
 
ea3338812e67
more tight interface for markup cumulate/select: avoid duplicate application, allow to defer decision about definedness;
 
wenzelm 
parents: 
52642 
diff
changeset
 | 
189  | 
var changed = false  | 
| 
 
ea3338812e67
more tight interface for markup cumulate/select: avoid duplicate application, allow to defer decision about definedness;
 
wenzelm 
parents: 
52642 
diff
changeset
 | 
190  | 
      for {
 | 
| 
55645
 
561754277494
tuned -- remaining rev_markup is rather short after filter;
 
wenzelm 
parents: 
55622 
diff
changeset
 | 
191  | 
elem <- entry.filter_markup(elements)  | 
| 55620 | 192  | 
y1 <- result(y, Text.Info(entry.range, elem))  | 
| 
52889
 
ea3338812e67
more tight interface for markup cumulate/select: avoid duplicate application, allow to defer decision about definedness;
 
wenzelm 
parents: 
52642 
diff
changeset
 | 
193  | 
      } { y = y1; changed = true }
 | 
| 
50552
 
2b7fd8c9c4ac
maintain subtree_elements for improved performance of cumulate operator;
 
wenzelm 
parents: 
50551 
diff
changeset
 | 
194  | 
if (changed) Some(y) else None  | 
| 
 
2b7fd8c9c4ac
maintain subtree_elements for improved performance of cumulate operator;
 
wenzelm 
parents: 
50551 
diff
changeset
 | 
195  | 
}  | 
| 45467 | 196  | 
|
| 
52900
 
d29bf6db8a2d
more elementary list structures for markup tree traversal;
 
wenzelm 
parents: 
52889 
diff
changeset
 | 
197  | 
def traverse(  | 
| 45459 | 198  | 
last: Text.Offset,  | 
| 75393 | 199  | 
stack: List[(Text.Info[A], List[(Text.Range, Entry)])]  | 
200  | 
    ): List[Text.Info[A]] = {
 | 
|
| 45459 | 201  | 
      stack match {
 | 
| 
52900
 
d29bf6db8a2d
more elementary list structures for markup tree traversal;
 
wenzelm 
parents: 
52889 
diff
changeset
 | 
202  | 
case (parent, (range, entry) :: more) :: rest =>  | 
| 45467 | 203  | 
val subrange = range.restrict(root_range)  | 
| 
55652
 
33ad12ef79ff
eliminated somewhat pointless elements index (see also f793dd5d84b2, 2b7fed8c9c4ac): less memory and more speed (avoid linear "exists" of 19dffae33cde);
 
wenzelm 
parents: 
55645 
diff
changeset
 | 
204  | 
val subtree = entry.subtree.overlapping(subrange).toList  | 
| 45459 | 205  | 
val start = subrange.start  | 
206  | 
||
| 
55652
 
33ad12ef79ff
eliminated somewhat pointless elements index (see also f793dd5d84b2, 2b7fed8c9c4ac): less memory and more speed (avoid linear "exists" of 19dffae33cde);
 
wenzelm 
parents: 
55645 
diff
changeset
 | 
207  | 
          results(parent.info, entry) match {
 | 
| 
45469
 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 
wenzelm 
parents: 
45468 
diff
changeset
 | 
208  | 
case Some(res) =>  | 
| 
 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 
wenzelm 
parents: 
45468 
diff
changeset
 | 
209  | 
val next = Text.Info(subrange, res)  | 
| 
52900
 
d29bf6db8a2d
more elementary list structures for markup tree traversal;
 
wenzelm 
parents: 
52889 
diff
changeset
 | 
210  | 
val nexts = traverse(start, (next, subtree) :: (parent, more) :: rest)  | 
| 
 
d29bf6db8a2d
more elementary list structures for markup tree traversal;
 
wenzelm 
parents: 
52889 
diff
changeset
 | 
211  | 
if (last < start) parent.restrict(Text.Range(last, start)) :: nexts  | 
| 
45469
 
25306d92f4ad
refined Markup_Tree implementation: stacked markup within each entry;
 
wenzelm 
parents: 
45468 
diff
changeset
 | 
212  | 
else nexts  | 
| 
52900
 
d29bf6db8a2d
more elementary list structures for markup tree traversal;
 
wenzelm 
parents: 
52889 
diff
changeset
 | 
213  | 
case None => traverse(last, (parent, subtree ::: more) :: rest)  | 
| 45459 | 214  | 
}  | 
215  | 
||
| 
52900
 
d29bf6db8a2d
more elementary list structures for markup tree traversal;
 
wenzelm 
parents: 
52889 
diff
changeset
 | 
216  | 
case (parent, Nil) :: rest =>  | 
| 45459 | 217  | 
val stop = parent.range.stop  | 
| 
52900
 
d29bf6db8a2d
more elementary list structures for markup tree traversal;
 
wenzelm 
parents: 
52889 
diff
changeset
 | 
218  | 
val nexts = traverse(stop, rest)  | 
| 
 
d29bf6db8a2d
more elementary list structures for markup tree traversal;
 
wenzelm 
parents: 
52889 
diff
changeset
 | 
219  | 
if (last < stop) parent.restrict(Text.Range(last, stop)) :: nexts  | 
| 45459 | 220  | 
else nexts  | 
221  | 
||
222  | 
case Nil =>  | 
|
| 45467 | 223  | 
val stop = root_range.stop  | 
| 
52900
 
d29bf6db8a2d
more elementary list structures for markup tree traversal;
 
wenzelm 
parents: 
52889 
diff
changeset
 | 
224  | 
if (last < stop) List(Text.Info(Text.Range(last, stop), root_info))  | 
| 
 
d29bf6db8a2d
more elementary list structures for markup tree traversal;
 
wenzelm 
parents: 
52889 
diff
changeset
 | 
225  | 
else Nil  | 
| 45459 | 226  | 
}  | 
227  | 
}  | 
|
| 
52900
 
d29bf6db8a2d
more elementary list structures for markup tree traversal;
 
wenzelm 
parents: 
52889 
diff
changeset
 | 
228  | 
traverse(root_range.start,  | 
| 
 
d29bf6db8a2d
more elementary list structures for markup tree traversal;
 
wenzelm 
parents: 
52889 
diff
changeset
 | 
229  | 
List((Text.Info(root_range, root_info), overlapping(root_range).toList)))  | 
| 45459 | 230  | 
}  | 
| 
56301
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
231  | 
|
| 75393 | 232  | 
  def to_XML(root_range: Text.Range, text: CharSequence, elements: Markup.Elements): XML.Body = {
 | 
| 
56301
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
233  | 
def make_text(start: Text.Offset, stop: Text.Offset): XML.Body =  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
234  | 
if (start == stop) Nil  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
235  | 
else List(XML.Text(text.subSequence(start, stop).toString))  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
236  | 
|
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
237  | 
def make_elems(rev_markups: List[XML.Elem], body: XML.Body): XML.Body =  | 
| 73359 | 238  | 
      rev_markups.foldLeft(body) {
 | 
| 
56301
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
239  | 
case (b, elem) =>  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
240  | 
if (!elements(elem.name)) b  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
241  | 
else if (elem.body.isEmpty) List(XML.Elem(elem.markup, b))  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
242  | 
else List(XML.Wrapped_Elem(elem.markup, elem.body, b))  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
243  | 
}  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
244  | 
|
| 75393 | 245  | 
def make_body(  | 
246  | 
elem_range: Text.Range,  | 
|
247  | 
elem_markup: List[XML.Elem],  | 
|
248  | 
entries: Branches.T  | 
|
249  | 
    ) : XML.Body = {
 | 
|
| 
56301
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
250  | 
val body = new mutable.ListBuffer[XML.Tree]  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
251  | 
var last = elem_range.start  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
252  | 
      for ((range, entry) <- entries) {
 | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
253  | 
val subrange = range.restrict(elem_range)  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
254  | 
body ++= make_text(last, subrange.start)  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
255  | 
body ++= make_body(subrange, entry.rev_markup, entry.subtree.overlapping(subrange))  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
256  | 
last = subrange.stop  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
257  | 
}  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
258  | 
body ++= make_text(last, elem_range.stop)  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
259  | 
make_elems(elem_markup, body.toList)  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
260  | 
}  | 
| 
75659
 
9bd92ac9328f
more robust Scala 3 indentation, for the sake of IntelliJ IDEA;
 
wenzelm 
parents: 
75393 
diff
changeset
 | 
261  | 
make_body(root_range, Nil, overlapping(root_range))  | 
| 
56301
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
262  | 
}  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
263  | 
|
| 57912 | 264  | 
override def toString: String =  | 
| 
56301
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
265  | 
    branches.toList.map(_._2) match {
 | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
266  | 
case Nil => "Empty"  | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
267  | 
      case list => list.mkString("Tree(", ",", ")")
 | 
| 
 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 
wenzelm 
parents: 
56300 
diff
changeset
 | 
268  | 
}  | 
| 
34717
 
3f32e08bbb6c
sidekick root data: set buffer length to avoid crash of initial caret move;
 
wenzelm 
parents: 
34708 
diff
changeset
 | 
269  | 
}  |