| author | wenzelm | 
| Wed, 21 Feb 2024 19:54:17 +0100 | |
| changeset 79683 | ade429ddb1fc | 
| parent 78913 | ecb02f288636 | 
| child 81406 | 4e9873629bff | 
| permissions | -rw-r--r-- | 
| 36676 | 1 | /* Title: Pure/PIDE/command.scala | 
| 2 | Author: Fabian Immler, TU Munich | |
| 3 | Author: Makarius | |
| 4 | ||
| 52536 | 5 | Prover commands with accumulated results from execution. | 
| 36676 | 6 | */ | 
| 34407 | 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: 
34865diff
changeset | 8 | package isabelle | 
| 34318 
c13e168a8ae6
original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
 wenzelm parents: diff
changeset | 9 | |
| 34451 | 10 | |
| 38872 | 11 | import scala.collection.immutable.SortedMap | 
| 12 | ||
| 13 | ||
| 75393 | 14 | object Command {
 | 
| 72814 | 15 | /* blobs */ | 
| 59702 
58dfaa369c11
hybrid use of command blobs: inlined errors and auxiliary files;
 wenzelm parents: 
59699diff
changeset | 16 | |
| 72745 | 17 | sealed case class Blob( | 
| 18 | name: Document.Node.Name, | |
| 72747 
5f9d66155081
clarified theory keywords: loaded_files are determined statically in Scala, but ML needs to do it semantically;
 wenzelm parents: 
72745diff
changeset | 19 | src_path: Path, | 
| 75393 | 20 | content: Option[(SHA1.Digest, Symbol.Text_Chunk)] | 
| 21 |   ) {
 | |
| 72816 
ea4f86914cb2
support for PIDE markup for auxiliary files ("blobs");
 wenzelm parents: 
72814diff
changeset | 22 | def chunk_file: Symbol.Text_Chunk.File = | 
| 
ea4f86914cb2
support for PIDE markup for auxiliary files ("blobs");
 wenzelm parents: 
72814diff
changeset | 23 | Symbol.Text_Chunk.File(name.node) | 
| 
ea4f86914cb2
support for PIDE markup for auxiliary files ("blobs");
 wenzelm parents: 
72814diff
changeset | 24 | } | 
| 72745 | 25 | |
| 75393 | 26 |   object Blobs_Info {
 | 
| 76914 | 27 | val empty: Blobs_Info = Blobs_Info(Nil) | 
| 72814 | 28 | |
| 76913 | 29 | def make(blobs: List[(Blob, Document.Blobs.Item)]): Blobs_Info = | 
| 76914 | 30 | if (blobs.isEmpty) empty else Blobs_Info(for ((a, _) <- blobs) yield Exn.Res(a)) | 
| 76913 | 31 | |
| 72814 | 32 | def errors(msgs: List[String]): Blobs_Info = | 
| 72846 | 33 | Blobs_Info(msgs.map(msg => Exn.Exn[Blob](ERROR(msg)))) | 
| 72814 | 34 | } | 
| 35 | ||
| 72846 | 36 | sealed case class Blobs_Info(blobs: List[Exn.Result[Blob]], index: Int = -1) | 
| 72814 | 37 | |
| 52849 | 38 | |
| 39 | ||
| 38361 | 40 | /** accumulated results from prover **/ | 
| 41 | ||
| 50507 | 42 | /* results */ | 
| 43 | ||
| 75393 | 44 |   object Results {
 | 
| 72869 | 45 | type Entry = (Long, XML.Elem) | 
| 68101 | 46 | val empty: Results = new Results(SortedMap.empty) | 
| 73362 | 47 | def make(args: IterableOnce[Results.Entry]): Results = | 
| 48 | args.iterator.foldLeft(empty)(_ + _) | |
| 49 | def merge(args: IterableOnce[Results]): Results = | |
| 50 | args.iterator.foldLeft(empty)(_ ++ _) | |
| 50507 | 51 | } | 
| 52 | ||
| 75393 | 53 |   final class Results private(private val rep: SortedMap[Long, XML.Elem]) {
 | 
| 64802 | 54 | def is_empty: Boolean = rep.isEmpty | 
| 50507 | 55 | def defined(serial: Long): Boolean = rep.isDefinedAt(serial) | 
| 72869 | 56 | def get(serial: Long): Option[XML.Elem] = rep.get(serial) | 
| 56372 
fadb0fef09d7
more explicit iterator terminology, in accordance to Scala 2.8 library;
 wenzelm parents: 
56359diff
changeset | 57 | def iterator: Iterator[Results.Entry] = rep.iterator | 
| 50508 
5b7150395568
tuned implementation according to Library.insert/merge in ML;
 wenzelm parents: 
50507diff
changeset | 58 | |
| 51496 
cb677987b7e3
retain original tooltip range, to avoid repeated window popup when the mouse is moved over the same content;
 wenzelm parents: 
51494diff
changeset | 59 | def + (entry: Results.Entry): Results = | 
| 50508 
5b7150395568
tuned implementation according to Library.insert/merge in ML;
 wenzelm parents: 
50507diff
changeset | 60 | if (defined(entry._1)) this | 
| 
5b7150395568
tuned implementation according to Library.insert/merge in ML;
 wenzelm parents: 
50507diff
changeset | 61 | else new Results(rep + entry) | 
| 
5b7150395568
tuned implementation according to Library.insert/merge in ML;
 wenzelm parents: 
50507diff
changeset | 62 | |
| 
5b7150395568
tuned implementation according to Library.insert/merge in ML;
 wenzelm parents: 
50507diff
changeset | 63 | def ++ (other: Results): Results = | 
| 
5b7150395568
tuned implementation according to Library.insert/merge in ML;
 wenzelm parents: 
50507diff
changeset | 64 | if (this eq other) this | 
| 
5b7150395568
tuned implementation according to Library.insert/merge in ML;
 wenzelm parents: 
50507diff
changeset | 65 | else if (rep.isEmpty) other | 
| 73359 | 66 | else other.iterator.foldLeft(this)(_ + _) | 
| 50540 | 67 | |
| 51494 | 68 | override def hashCode: Int = rep.hashCode | 
| 69 | override def equals(that: Any): Boolean = | |
| 70 |       that match {
 | |
| 71 | case other: Results => rep == other.rep | |
| 72 | case _ => false | |
| 73 | } | |
| 56372 
fadb0fef09d7
more explicit iterator terminology, in accordance to Scala 2.8 library;
 wenzelm parents: 
56359diff
changeset | 74 |     override def toString: String = iterator.mkString("Results(", ", ", ")")
 | 
| 50507 | 75 | } | 
| 76 | ||
| 77 | ||
| 68101 | 78 | /* exports */ | 
| 79 | ||
| 75393 | 80 |   object Exports {
 | 
| 68101 | 81 | type Entry = (Long, Export.Entry) | 
| 82 | val empty: Exports = new Exports(SortedMap.empty) | |
| 73362 | 83 | def merge(args: IterableOnce[Exports]): Exports = | 
| 84 | args.iterator.foldLeft(empty)(_ ++ _) | |
| 68101 | 85 | } | 
| 86 | ||
| 75393 | 87 |   final class Exports private(private val rep: SortedMap[Long, Export.Entry]) {
 | 
| 69634 | 88 | def is_empty: Boolean = rep.isEmpty | 
| 68101 | 89 | def iterator: Iterator[Exports.Entry] = rep.iterator | 
| 90 | ||
| 91 | def + (entry: Exports.Entry): Exports = | |
| 92 | if (rep.isDefinedAt(entry._1)) this | |
| 93 | else new Exports(rep + entry) | |
| 94 | ||
| 95 | def ++ (other: Exports): Exports = | |
| 96 | if (this eq other) this | |
| 97 | else if (rep.isEmpty) other | |
| 73359 | 98 | else other.iterator.foldLeft(this)(_ + _) | 
| 68101 | 99 | |
| 100 | override def hashCode: Int = rep.hashCode | |
| 101 | override def equals(that: Any): Boolean = | |
| 102 |       that match {
 | |
| 103 | case other: Exports => rep == other.rep | |
| 104 | case _ => false | |
| 105 | } | |
| 106 |     override def toString: String = iterator.mkString("Exports(", ", ", ")")
 | |
| 107 | } | |
| 108 | ||
| 109 | ||
| 110 | /* markups */ | |
| 55649 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 111 | |
| 75393 | 112 |   object Markup_Index {
 | 
| 56746 | 113 | val markup: Markup_Index = Markup_Index(false, Symbol.Text_Chunk.Default) | 
| 72816 
ea4f86914cb2
support for PIDE markup for auxiliary files ("blobs");
 wenzelm parents: 
72814diff
changeset | 114 | def blob(blob: Blob): Markup_Index = Markup_Index(false, blob.chunk_file) | 
| 76912 
ca872f20cf5b
clarified session sources: theory and blobs are read from database, instead of physical file-system;
 wenzelm parents: 
76908diff
changeset | 115 | def make(blobs: List[Blob]): List[Markup_Index] = markup :: blobs.map(blob) | 
| 55649 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 116 | } | 
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 117 | |
| 56746 | 118 | sealed case class Markup_Index(status: Boolean, chunk_name: Symbol.Text_Chunk.Name) | 
| 55649 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 119 | |
| 75393 | 120 |   object Markups {
 | 
| 72848 
d5d0e36eda16
read theory with PIDE markup from session database;
 wenzelm parents: 
72846diff
changeset | 121 | type Entry = (Markup_Index, Markup_Tree) | 
| 55649 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 122 | val empty: Markups = new Markups(Map.empty) | 
| 65335 | 123 | def init(markup: Markup_Tree): Markups = new Markups(Map(Markup_Index.markup -> markup)) | 
| 73362 | 124 | def make(args: IterableOnce[Entry]): Markups = | 
| 125 | args.iterator.foldLeft(empty)(_ + _) | |
| 126 | def merge(args: IterableOnce[Markups]): Markups = | |
| 127 | args.iterator.foldLeft(empty)(_ ++ _) | |
| 55649 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 128 | } | 
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 129 | |
| 75393 | 130 |   final class Markups private(private val rep: Map[Markup_Index, Markup_Tree]) {
 | 
| 56489 | 131 | def is_empty: Boolean = rep.isEmpty | 
| 132 | ||
| 55649 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 133 | def apply(index: Markup_Index): Markup_Tree = | 
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 134 | rep.getOrElse(index, Markup_Tree.empty) | 
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 135 | |
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 136 | def add(index: Markup_Index, markup: Text.Markup): Markups = | 
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 137 | new Markups(rep + (index -> (this(index) + markup))) | 
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 138 | |
| 75393 | 139 |     def + (entry: Markups.Entry): Markups = {
 | 
| 65335 | 140 | val (index, tree) = entry | 
| 141 | new Markups(rep + (index -> (this(index).merge(tree, Text.Range.full, Markup.Elements.full)))) | |
| 142 | } | |
| 143 | ||
| 144 | def ++ (other: Markups): Markups = | |
| 145 | if (this eq other) this | |
| 146 | else if (rep.isEmpty) other | |
| 73359 | 147 | else other.rep.iterator.foldLeft(this)(_ + _) | 
| 65335 | 148 | |
| 56475 | 149 | def redirection_iterator: Iterator[Document_ID.Generic] = | 
| 78592 | 150 | for (case Markup_Index(_, Symbol.Text_Chunk.Id(id)) <- rep.keysIterator) | 
| 56475 | 151 | yield id | 
| 56470 
8eda56033203
accumulate markup reports for "other" command ids, which are later retargeted and merged for rendering (in erratic order);
 wenzelm parents: 
56469diff
changeset | 152 | |
| 75393 | 153 |     def redirect(other_id: Document_ID.Generic): Markups = {
 | 
| 56489 | 154 | val rep1 = | 
| 56470 
8eda56033203
accumulate markup reports for "other" command ids, which are later retargeted and merged for rendering (in erratic order);
 wenzelm parents: 
56469diff
changeset | 155 |         (for {
 | 
| 78592 | 156 | case (Markup_Index(status, Symbol.Text_Chunk.Id(id)), markup) <- rep.iterator | 
| 56470 
8eda56033203
accumulate markup reports for "other" command ids, which are later retargeted and merged for rendering (in erratic order);
 wenzelm parents: 
56469diff
changeset | 157 | if other_id == id | 
| 56746 | 158 | } yield (Markup_Index(status, Symbol.Text_Chunk.Default), markup)).toMap | 
| 56489 | 159 | if (rep1.isEmpty) Markups.empty else new Markups(rep1) | 
| 160 | } | |
| 56470 
8eda56033203
accumulate markup reports for "other" command ids, which are later retargeted and merged for rendering (in erratic order);
 wenzelm parents: 
56469diff
changeset | 161 | |
| 55649 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 162 | override def hashCode: Int = rep.hashCode | 
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 163 | override def equals(that: Any): Boolean = | 
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 164 |       that match {
 | 
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 165 | case other: Markups => rep == other.rep | 
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 166 | case _ => false | 
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 167 | } | 
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 168 |     override def toString: String = rep.iterator.mkString("Markups(", ", ", ")")
 | 
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 169 | } | 
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 170 | |
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 171 | |
| 50507 | 172 | /* state */ | 
| 50501 
6f41f1646617
more careful handling of Dialog_Result, with active area and color feedback;
 wenzelm parents: 
50500diff
changeset | 173 | |
| 75393 | 174 |   object State {
 | 
| 72869 | 175 | def get_result(states: List[State], serial: Long): Option[XML.Elem] = | 
| 67824 
661cd25304ae
more compact markup tree: output messages are already stored in command results (e.g. relevant for  XML data representation);
 wenzelm parents: 
67446diff
changeset | 176 | states.find(st => st.results.defined(serial)).map(st => st.results.get(serial).get) | 
| 
661cd25304ae
more compact markup tree: output messages are already stored in command results (e.g. relevant for  XML data representation);
 wenzelm parents: 
67446diff
changeset | 177 | |
| 
661cd25304ae
more compact markup tree: output messages are already stored in command results (e.g. relevant for  XML data representation);
 wenzelm parents: 
67446diff
changeset | 178 | def get_result_proper(states: List[State], props: Properties.T): Option[Results.Entry] = | 
| 
661cd25304ae
more compact markup tree: output messages are already stored in command results (e.g. relevant for  XML data representation);
 wenzelm parents: 
67446diff
changeset | 179 |       for {
 | 
| 
661cd25304ae
more compact markup tree: output messages are already stored in command results (e.g. relevant for  XML data representation);
 wenzelm parents: 
67446diff
changeset | 180 | serial <- Markup.Serial.unapply(props) | 
| 72869 | 181 | elem <- get_result(states, serial) | 
| 182 | if elem.body.nonEmpty | |
| 183 | } yield serial -> elem | |
| 67824 
661cd25304ae
more compact markup tree: output messages are already stored in command results (e.g. relevant for  XML data representation);
 wenzelm parents: 
67446diff
changeset | 184 | |
| 65335 | 185 | def merge_results(states: List[State]): Results = | 
| 56299 
8201790fdeb9
more careful treatment of multiple command states (eval + prints): merge content that is actually required;
 wenzelm parents: 
56295diff
changeset | 186 | Results.merge(states.map(_.results)) | 
| 
8201790fdeb9
more careful treatment of multiple command states (eval + prints): merge content that is actually required;
 wenzelm parents: 
56295diff
changeset | 187 | |
| 68101 | 188 | def merge_exports(states: List[State]): Exports = | 
| 189 | Exports.merge(states.map(_.exports)) | |
| 190 | ||
| 65335 | 191 | def merge_markups(states: List[State]): Markups = | 
| 192 | Markups.merge(states.map(_.markups)) | |
| 193 | ||
| 56301 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 wenzelm parents: 
56299diff
changeset | 194 | def merge_markup(states: List[State], index: Markup_Index, | 
| 56743 | 195 | range: Text.Range, elements: Markup.Elements): Markup_Tree = | 
| 56301 
1da7b4c33db9
more frugal merge of markup trees: filter wrt. subsequent query;
 wenzelm parents: 
56299diff
changeset | 196 | Markup_Tree.merge(states.map(_.markup(index)), range, elements) | 
| 65335 | 197 | |
| 198 | def merge(command: Command, states: List[State]): State = | |
| 68101 | 199 | State(command, states.flatMap(_.status), merge_results(states), | 
| 200 | merge_exports(states), merge_markups(states)) | |
| 56299 
8201790fdeb9
more careful treatment of multiple command states (eval + prints): merge content that is actually required;
 wenzelm parents: 
56295diff
changeset | 201 | } | 
| 
8201790fdeb9
more careful treatment of multiple command states (eval + prints): merge content that is actually required;
 wenzelm parents: 
56295diff
changeset | 202 | |
| 43714 | 203 | sealed case class State( | 
| 50501 
6f41f1646617
more careful handling of Dialog_Result, with active area and color feedback;
 wenzelm parents: 
50500diff
changeset | 204 | command: Command, | 
| 
6f41f1646617
more careful handling of Dialog_Result, with active area and color feedback;
 wenzelm parents: 
50500diff
changeset | 205 | status: List[Markup] = Nil, | 
| 50507 | 206 | results: Results = Results.empty, | 
| 68101 | 207 | exports: Exports = Exports.empty, | 
| 75393 | 208 | markups: Markups = Markups.empty | 
| 209 |   ) {
 | |
| 76473 | 210 | lazy val initialized: Boolean = status.exists(markup => markup.name == Markup.INITIALIZED) | 
| 211 | lazy val consolidating: Boolean = status.exists(markup => markup.name == Markup.CONSOLIDATING) | |
| 212 | lazy val consolidated: Boolean = status.exists(markup => markup.name == Markup.CONSOLIDATED) | |
| 66379 
6392766f3c25
maintain "consolidated" status of theory nodes, which means all evals are finished (but not necessarily prints nor imports);
 wenzelm parents: 
65522diff
changeset | 213 | |
| 75393 | 214 |     lazy val maybe_consolidated: Boolean = {
 | 
| 68758 | 215 | var touched = false | 
| 216 | var forks = 0 | |
| 217 | var runs = 0 | |
| 218 |       for (markup <- status) {
 | |
| 219 |         markup.name match {
 | |
| 220 | case Markup.FORKED => touched = true; forks += 1 | |
| 221 | case Markup.JOINED => forks -= 1 | |
| 222 | case Markup.RUNNING => touched = true; runs += 1 | |
| 223 | case Markup.FINISHED => runs -= 1 | |
| 224 | case _ => | |
| 225 | } | |
| 226 | } | |
| 227 | touched && forks == 0 && runs == 0 | |
| 228 | } | |
| 68381 
2fd3a6d6ba2e
less wasteful consolidation, based on PIDE front-end state and recent changes;
 wenzelm parents: 
68335diff
changeset | 229 | |
| 75393 | 230 |     lazy val document_status: Document_Status.Command_Status = {
 | 
| 56395 
0546e036d1c0
more direct warning within persistent Protocol.Status;
 wenzelm parents: 
56372diff
changeset | 231 | val warnings = | 
| 59203 
5f0bd5afc16d
explicit message channel for "legacy", which is nonetheless a variant of "warning";
 wenzelm parents: 
59072diff
changeset | 232 | if (results.iterator.exists(p => Protocol.is_warning(p._2) || Protocol.is_legacy(p._2))) | 
| 56395 
0546e036d1c0
more direct warning within persistent Protocol.Status;
 wenzelm parents: 
56372diff
changeset | 233 | List(Markup(Markup.WARNING, Nil)) | 
| 
0546e036d1c0
more direct warning within persistent Protocol.Status;
 wenzelm parents: 
56372diff
changeset | 234 | else Nil | 
| 
0546e036d1c0
more direct warning within persistent Protocol.Status;
 wenzelm parents: 
56372diff
changeset | 235 | val errors = | 
| 
0546e036d1c0
more direct warning within persistent Protocol.Status;
 wenzelm parents: 
56372diff
changeset | 236 | if (results.iterator.exists(p => Protocol.is_error(p._2))) | 
| 
0546e036d1c0
more direct warning within persistent Protocol.Status;
 wenzelm parents: 
56372diff
changeset | 237 | List(Markup(Markup.ERROR, Nil)) | 
| 
0546e036d1c0
more direct warning within persistent Protocol.Status;
 wenzelm parents: 
56372diff
changeset | 238 | else Nil | 
| 68758 | 239 | Document_Status.Command_Status.make((warnings ::: errors ::: status).iterator) | 
| 56395 
0546e036d1c0
more direct warning within persistent Protocol.Status;
 wenzelm parents: 
56372diff
changeset | 240 | } | 
| 55432 
9c53198dbb1c
maintain multiple command chunks and markup trees: for main chunk and loaded files;
 wenzelm parents: 
55431diff
changeset | 241 | |
| 55650 | 242 | def markup(index: Markup_Index): Markup_Tree = markups(index) | 
| 55432 
9c53198dbb1c
maintain multiple command chunks and markup trees: for main chunk and loaded files;
 wenzelm parents: 
55431diff
changeset | 243 | |
| 75393 | 244 |     def redirect(other_command: Command): Option[State] = {
 | 
| 56489 | 245 | val markups1 = markups.redirect(other_command.id) | 
| 246 | if (markups1.is_empty) None | |
| 68101 | 247 | else Some(new State(other_command, markups = markups1)) | 
| 56489 | 248 | } | 
| 49614 | 249 | |
| 55649 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 250 | private def add_status(st: Markup): State = | 
| 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 251 | copy(status = st :: status) | 
| 55432 
9c53198dbb1c
maintain multiple command chunks and markup trees: for main chunk and loaded files;
 wenzelm parents: 
55431diff
changeset | 252 | |
| 67826 | 253 | private def add_result(entry: Results.Entry): State = | 
| 254 | copy(results = results + entry) | |
| 255 | ||
| 68114 | 256 | def add_export(entry: Exports.Entry): Option[State] = | 
| 257 | if (command.node_name.theory == entry._2.theory_name) Some(copy(exports = exports + entry)) | |
| 258 | else None | |
| 68101 | 259 | |
| 56746 | 260 | private def add_markup( | 
| 75393 | 261 | status: Boolean, | 
| 262 | chunk_name: Symbol.Text_Chunk.Name, | |
| 263 | m: Text.Markup | |
| 264 |     ): State = {
 | |
| 55649 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 265 | val markups1 = | 
| 68758 | 266 | if (status || Document_Status.Command_Status.liberal_elements(m.info.name)) | 
| 56462 
b64b0cb845fe
more explicit Command.Chunk types, less ooddities;
 wenzelm parents: 
56395diff
changeset | 267 | markups.add(Markup_Index(true, chunk_name), m) | 
| 55649 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 268 | else markups | 
| 56462 
b64b0cb845fe
more explicit Command.Chunk types, less ooddities;
 wenzelm parents: 
56395diff
changeset | 269 | copy(markups = markups1.add(Markup_Index(false, chunk_name), m)) | 
| 55649 
1532ab0dc67b
more general / abstract Command.Markups, with separate index for status elements;
 wenzelm parents: 
55648diff
changeset | 270 | } | 
| 38361 | 271 | |
| 56470 
8eda56033203
accumulate markup reports for "other" command ids, which are later retargeted and merged for rendering (in erratic order);
 wenzelm parents: 
56469diff
changeset | 272 | def accumulate( | 
| 
8eda56033203
accumulate markup reports for "other" command ids, which are later retargeted and merged for rendering (in erratic order);
 wenzelm parents: 
56469diff
changeset | 273 | self_id: Document_ID.Generic => Boolean, | 
| 72780 | 274 | other_id: (Document.Node.Name, Document_ID.Generic) => | 
| 275 | Option[(Symbol.Text_Chunk.Id, Symbol.Text_Chunk)], | |
| 67825 | 276 | message: XML.Elem, | 
| 73031 
f93f0597f4fb
clarified signature: absorb XZ.Cache into XML.Cache;
 wenzelm parents: 
72962diff
changeset | 277 | cache: XML.Cache): State = | 
| 38361 | 278 |       message match {
 | 
| 50201 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
50163diff
changeset | 279 | case XML.Elem(Markup(Markup.STATUS, _), msgs) => | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 280 | if (command.span.is_theory) this | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 281 |           else {
 | 
| 73359 | 282 |             msgs.foldLeft(this) {
 | 
| 283 | case (state, msg) => | |
| 284 |                 msg match {
 | |
| 285 | case elem @ XML.Elem(markup, Nil) => | |
| 286 | state. | |
| 287 | add_status(markup). | |
| 288 | add_markup(true, Symbol.Text_Chunk.Default, Text.Info(command.core_range, elem)) | |
| 289 | case _ => | |
| 290 |                     Output.warning("Ignored status message: " + msg)
 | |
| 291 | state | |
| 292 | } | |
| 293 | } | |
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 294 | } | 
| 38581 
d503a0912e14
simplified Command.status again, reverting most of e5eed57913d0 (note that more complex information can be represented with full markup reports);
 wenzelm parents: 
38579diff
changeset | 295 | |
| 72709 
cb9d5af781b4
more complete report positions, notably for command 'back' (amending eca176f773e0);
 wenzelm parents: 
72708diff
changeset | 296 | case XML.Elem(Markup(Markup.REPORT, atts0), msgs) => | 
| 73359 | 297 |           msgs.foldLeft(this) {
 | 
| 298 | case (state, msg) => | |
| 56782 
433cf57550fa
more systematic Isabelle output, like in classic Isabelle/ML (without markup);
 wenzelm parents: 
56746diff
changeset | 299 |               def bad(): Unit = Output.warning("Ignored report message: " + msg)
 | 
| 55432 
9c53198dbb1c
maintain multiple command chunks and markup trees: for main chunk and loaded files;
 wenzelm parents: 
55431diff
changeset | 300 | |
| 
9c53198dbb1c
maintain multiple command chunks and markup trees: for main chunk and loaded files;
 wenzelm parents: 
55431diff
changeset | 301 |               msg match {
 | 
| 72826 
fa5d8f486380
proper treatment of singleton Position.Offset within blob (amending cb9d5af781b4);
 wenzelm parents: 
72824diff
changeset | 302 | case XML.Elem(Markup(name, atts), args) => | 
| 
fa5d8f486380
proper treatment of singleton Position.Offset within blob (amending cb9d5af781b4);
 wenzelm parents: 
72824diff
changeset | 303 |                   command.reported_position(atts) orElse command.reported_position(atts0) match {
 | 
| 
fa5d8f486380
proper treatment of singleton Position.Offset within blob (amending cb9d5af781b4);
 wenzelm parents: 
72824diff
changeset | 304 | case Some((id, chunk_name, target_range)) => | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 305 | val target = | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 306 | if (self_id(id) && command.chunks.isDefinedAt(chunk_name)) | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 307 | Some((chunk_name, command.chunks(chunk_name))) | 
| 72780 | 308 | else if (chunk_name == Symbol.Text_Chunk.Default) | 
| 309 | other_id(command.node_name, id) | |
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 310 | else None | 
| 56470 
8eda56033203
accumulate markup reports for "other" command ids, which are later retargeted and merged for rendering (in erratic order);
 wenzelm parents: 
56469diff
changeset | 311 | |
| 72826 
fa5d8f486380
proper treatment of singleton Position.Offset within blob (amending cb9d5af781b4);
 wenzelm parents: 
72824diff
changeset | 312 |                       (target, target_range) match {
 | 
| 72831 
ffae996e9c08
silently ignore markup that starts out as singularity, e.g. <language/> from empty ML file;
 wenzelm parents: 
72827diff
changeset | 313 | case (Some((target_name, target_chunk)), Some(symbol_range)) | 
| 
ffae996e9c08
silently ignore markup that starts out as singularity, e.g. <language/> from empty ML file;
 wenzelm parents: 
72827diff
changeset | 314 | if !symbol_range.is_singularity => | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 315 |                           target_chunk.incorporate(symbol_range) match {
 | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 316 | case Some(range) => | 
| 72708 | 317 | val props = atts.filterNot(Markup.position_property) | 
| 73031 
f93f0597f4fb
clarified signature: absorb XZ.Cache into XML.Cache;
 wenzelm parents: 
72962diff
changeset | 318 | val elem = cache.elem(XML.Elem(Markup(name, props), args)) | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 319 | state.add_markup(false, target_name, Text.Info(range, elem)) | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 320 | case None => bad(); state | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 321 | } | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 322 | case _ => | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 323 | // silently ignore excessive reports | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 324 | state | 
| 55432 
9c53198dbb1c
maintain multiple command chunks and markup trees: for main chunk and loaded files;
 wenzelm parents: 
55431diff
changeset | 325 | } | 
| 
9c53198dbb1c
maintain multiple command chunks and markup trees: for main chunk and loaded files;
 wenzelm parents: 
55431diff
changeset | 326 | |
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 327 | case _ => bad(); state | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 328 | } | 
| 56470 
8eda56033203
accumulate markup reports for "other" command ids, which are later retargeted and merged for rendering (in erratic order);
 wenzelm parents: 
56469diff
changeset | 329 | case _ => bad(); state | 
| 55432 
9c53198dbb1c
maintain multiple command chunks and markup trees: for main chunk and loaded files;
 wenzelm parents: 
55431diff
changeset | 330 | } | 
| 73359 | 331 | } | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 332 | |
| 52930 
5fab62ae3532
retain original messages properties, e.g. for retrieval via Command.Results;
 wenzelm parents: 
52849diff
changeset | 333 | case XML.Elem(Markup(name, props), body) => | 
| 
5fab62ae3532
retain original messages properties, e.g. for retrieval via Command.Results;
 wenzelm parents: 
52849diff
changeset | 334 |           props match {
 | 
| 50201 
c26369c9eda6
Isabelle-specific implementation of quasi-abstract markup elements -- back to module arrangement before d83797ef0d2d;
 wenzelm parents: 
50163diff
changeset | 335 | case Markup.Serial(i) => | 
| 67825 | 336 | val markup_message = | 
| 76680 | 337 | cache.elem(Protocol.make_message(body, name, props = props)) | 
| 67825 | 338 | val message_markup = | 
| 73031 
f93f0597f4fb
clarified signature: absorb XZ.Cache into XML.Cache;
 wenzelm parents: 
72962diff
changeset | 339 | cache.elem(XML.elem(Markup(name, props.filter(p => p._1 == Markup.SERIAL)))) | 
| 50163 
c62ce309dc26
more abstract Sendback operations, with explicit id/exec_id properties;
 wenzelm parents: 
50158diff
changeset | 340 | |
| 67826 | 341 | var st = add_result(i -> markup_message) | 
| 55433 
d2960d67f163
clarified message_positions: cover alt_id as well;
 wenzelm parents: 
55432diff
changeset | 342 |               if (Protocol.is_inlined(message)) {
 | 
| 
d2960d67f163
clarified message_positions: cover alt_id as well;
 wenzelm parents: 
55432diff
changeset | 343 |                 for {
 | 
| 56469 | 344 | (chunk_name, chunk) <- command.chunks.iterator | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 345 | range <- command.message_positions(self_id, chunk_name, chunk, message) | 
| 67824 
661cd25304ae
more compact markup tree: output messages are already stored in command results (e.g. relevant for  XML data representation);
 wenzelm parents: 
67446diff
changeset | 346 | } st = st.add_markup(false, chunk_name, Text.Info(range, message_markup)) | 
| 55433 
d2960d67f163
clarified message_positions: cover alt_id as well;
 wenzelm parents: 
55432diff
changeset | 347 | } | 
| 
d2960d67f163
clarified message_positions: cover alt_id as well;
 wenzelm parents: 
55432diff
changeset | 348 | st | 
| 55432 
9c53198dbb1c
maintain multiple command chunks and markup trees: for main chunk and loaded files;
 wenzelm parents: 
55431diff
changeset | 349 | |
| 52536 | 350 | case _ => | 
| 56782 
433cf57550fa
more systematic Isabelle output, like in classic Isabelle/ML (without markup);
 wenzelm parents: 
56746diff
changeset | 351 |               Output.warning("Ignored message without serial number: " + message)
 | 
| 52536 | 352 | this | 
| 38872 | 353 | } | 
| 68101 | 354 | } | 
| 38361 | 355 | } | 
| 38367 | 356 | |
| 357 | ||
| 55431 
e0f20a44ff9d
common Command.Chunk for command source and auxiliary files (static Symbol.Index without actual String content);
 wenzelm parents: 
55430diff
changeset | 358 | |
| 
e0f20a44ff9d
common Command.Chunk for command source and auxiliary files (static Symbol.Index without actual String content);
 wenzelm parents: 
55430diff
changeset | 359 | /** static content **/ | 
| 
e0f20a44ff9d
common Command.Chunk for command source and auxiliary files (static Symbol.Index without actual String content);
 wenzelm parents: 
55430diff
changeset | 360 | |
| 45644 | 361 | /* make commands */ | 
| 362 | ||
| 55648 
38f264741609
tuned signature -- avoid obscure default arguments;
 wenzelm parents: 
55622diff
changeset | 363 | def apply( | 
| 
38f264741609
tuned signature -- avoid obscure default arguments;
 wenzelm parents: 
55622diff
changeset | 364 | id: Document_ID.Command, | 
| 
38f264741609
tuned signature -- avoid obscure default arguments;
 wenzelm parents: 
55622diff
changeset | 365 | node_name: Document.Node.Name, | 
| 59702 
58dfaa369c11
hybrid use of command blobs: inlined errors and auxiliary files;
 wenzelm parents: 
59699diff
changeset | 366 | blobs_info: Blobs_Info, | 
| 75393 | 367 | span: Command_Span.Span | 
| 368 |   ): Command = {
 | |
| 57901 
e1abca2527da
more explicit type Span in Scala, according to ML version;
 wenzelm parents: 
57842diff
changeset | 369 | val (source, span1) = span.compact_source | 
| 72722 
ade53fbc6f03
clarified signature: initial markup is_empty, not init_markup;
 wenzelm parents: 
72709diff
changeset | 370 | new Command(id, node_name, blobs_info, span1, source, Results.empty, Markups.empty) | 
| 55648 
38f264741609
tuned signature -- avoid obscure default arguments;
 wenzelm parents: 
55622diff
changeset | 371 | } | 
| 49414 | 372 | |
| 57901 
e1abca2527da
more explicit type Span in Scala, according to ML version;
 wenzelm parents: 
57842diff
changeset | 373 | val empty: Command = | 
| 76914 | 374 | Command(Document_ID.none, Document.Node.Name.empty, Blobs_Info.empty, Command_Span.empty) | 
| 55648 
38f264741609
tuned signature -- avoid obscure default arguments;
 wenzelm parents: 
55622diff
changeset | 375 | |
| 
38f264741609
tuned signature -- avoid obscure default arguments;
 wenzelm parents: 
55622diff
changeset | 376 | def unparsed( | 
| 
38f264741609
tuned signature -- avoid obscure default arguments;
 wenzelm parents: 
55622diff
changeset | 377 | source: String, | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 378 | theory: Boolean = false, | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 379 | id: Document_ID.Command = Document_ID.none, | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 380 | node_name: Document.Node.Name = Document.Node.Name.empty, | 
| 76914 | 381 | blobs_info: Blobs_Info = Blobs_Info.empty, | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 382 | results: Results = Results.empty, | 
| 75393 | 383 | markups: Markups = Markups.empty | 
| 384 |   ): Command = {
 | |
| 78913 | 385 | val (source1, span1) = Command_Span.unparsed(source, theory = theory).compact_source | 
| 72816 
ea4f86914cb2
support for PIDE markup for auxiliary files ("blobs");
 wenzelm parents: 
72814diff
changeset | 386 | new Command(id, node_name, blobs_info, span1, source1, results, markups) | 
| 55648 
38f264741609
tuned signature -- avoid obscure default arguments;
 wenzelm parents: 
55622diff
changeset | 387 | } | 
| 49414 | 388 | |
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 389 | def text(source: String): Command = unparsed(source) | 
| 44384 | 390 | |
| 52530 
99dd8b4ef3fe
explicit module Document_ID as source of globally unique identifiers across ML/Scala;
 wenzelm parents: 
52527diff
changeset | 391 | def rich_text(id: Document_ID.Command, results: Results, body: XML.Body): Command = | 
| 72722 
ade53fbc6f03
clarified signature: initial markup is_empty, not init_markup;
 wenzelm parents: 
72709diff
changeset | 392 | unparsed(XML.content(body), id = id, results = results, | 
| 
ade53fbc6f03
clarified signature: initial markup is_empty, not init_markup;
 wenzelm parents: 
72709diff
changeset | 393 | markups = Markups.init(Markup_Tree.from_XML(body))) | 
| 49359 
c1262d7389fb
refined output panel: more value-oriented approach to update and caret focus;
 wenzelm parents: 
49037diff
changeset | 394 | |
| 44384 | 395 | |
| 72814 | 396 | /* edits and perspective */ | 
| 397 | ||
| 398 | type Edit = (Option[Command], Option[Command]) | |
| 44384 | 399 | |
| 75393 | 400 |   object Perspective {
 | 
| 44474 | 401 | val empty: Perspective = Perspective(Nil) | 
| 402 | } | |
| 44385 
e7fdb008aa7d
propagate editor perspective through document model;
 wenzelm parents: 
44384diff
changeset | 403 | |
| 75393 | 404 | sealed case class Perspective( | 
| 405 | commands: List[Command] // visible commands in canonical order | |
| 406 |   ) {
 | |
| 57615 
df1b3452d71c
more explicit discrimination of empty nodes -- suppress from Theories panel;
 wenzelm parents: 
56782diff
changeset | 407 | def is_empty: Boolean = commands.isEmpty | 
| 
df1b3452d71c
more explicit discrimination of empty nodes -- suppress from Theories panel;
 wenzelm parents: 
56782diff
changeset | 408 | |
| 75393 | 409 |     def same(that: Perspective): Boolean = {
 | 
| 44474 | 410 | val cmds1 = this.commands | 
| 411 | val cmds2 = that.commands | |
| 73120 
c3589f2dff31
more informative errors: simplify diagnosis of spurious failures reported by users;
 wenzelm parents: 
73115diff
changeset | 412 | require(!cmds1.exists(_.is_undefined), "cmds1 not defined") | 
| 
c3589f2dff31
more informative errors: simplify diagnosis of spurious failures reported by users;
 wenzelm parents: 
73115diff
changeset | 413 | require(!cmds2.exists(_.is_undefined), "cmds2 not defined") | 
| 44474 | 414 | cmds1.length == cmds2.length && | 
| 415 |         (cmds1.iterator zip cmds2.iterator).forall({ case (c1, c2) => c1.id == c2.id })
 | |
| 416 | } | |
| 44385 
e7fdb008aa7d
propagate editor perspective through document model;
 wenzelm parents: 
44384diff
changeset | 417 | } | 
| 59689 
7968c57ea240
simplified Command.resolve_files in ML, using blobs_index from Scala;
 wenzelm parents: 
59684diff
changeset | 418 | |
| 
7968c57ea240
simplified Command.resolve_files in ML, using blobs_index from Scala;
 wenzelm parents: 
59684diff
changeset | 419 | |
| 59702 
58dfaa369c11
hybrid use of command blobs: inlined errors and auxiliary files;
 wenzelm parents: 
59699diff
changeset | 420 | /* blobs: inlined errors and auxiliary files */ | 
| 59689 
7968c57ea240
simplified Command.resolve_files in ML, using blobs_index from Scala;
 wenzelm parents: 
59684diff
changeset | 421 | |
| 59702 
58dfaa369c11
hybrid use of command blobs: inlined errors and auxiliary files;
 wenzelm parents: 
59699diff
changeset | 422 | def blobs_info( | 
| 59699 | 423 | resources: Resources, | 
| 63584 
68751fe1c036
tuned signature -- prover-independence is presently theoretical;
 wenzelm parents: 
62969diff
changeset | 424 | syntax: Outer_Syntax, | 
| 76904 
e27d097d7d15
tuned signature: avoid confusion with Document.Node.Blob and Command.Blob;
 wenzelm parents: 
76879diff
changeset | 425 | get_blob: Document.Node.Name => Option[Document.Blobs.Item], | 
| 59702 
58dfaa369c11
hybrid use of command blobs: inlined errors and auxiliary files;
 wenzelm parents: 
59699diff
changeset | 426 | can_import: Document.Node.Name => Boolean, | 
| 59699 | 427 | node_name: Document.Node.Name, | 
| 75393 | 428 | span: Command_Span.Span | 
| 429 |   ): Blobs_Info = {
 | |
| 59735 | 430 |     span.name match {
 | 
| 59702 
58dfaa369c11
hybrid use of command blobs: inlined errors and auxiliary files;
 wenzelm parents: 
59699diff
changeset | 431 | // inlined errors | 
| 59735 | 432 | case Thy_Header.THEORY => | 
| 72946 | 433 | val reader = span.content_reader | 
| 434 | val header = resources.check_thy(node_name, span.content_reader) | |
| 72748 
04d5f6d769a7
more flexible syntax for theory load commands via Isabelle/Scala;
 wenzelm parents: 
72747diff
changeset | 435 | val imports_pos = header.imports_pos | 
| 66768 | 436 | val raw_imports = | 
| 437 |           try {
 | |
| 72778 | 438 | val read_imports = Thy_Header.read(node_name, reader).imports.map(_._1) | 
| 70638 
f164cec7ac22
clarified signature: prefer operations without position;
 wenzelm parents: 
69891diff
changeset | 439 |             if (imports_pos.length == read_imports.length) read_imports else error("")
 | 
| 66768 | 440 | } | 
| 72778 | 441 |           catch { case _: Throwable => List.fill(header.imports.length)("") }
 | 
| 66768 | 442 | |
| 72765 | 443 | val errors = | 
| 70638 
f164cec7ac22
clarified signature: prefer operations without position;
 wenzelm parents: 
69891diff
changeset | 444 |           for { ((import_name, pos), s) <- imports_pos zip raw_imports if !can_import(import_name) }
 | 
| 66768 | 445 |           yield {
 | 
| 446 | val completion = | |
| 76828 | 447 | if (Url.is_base_name(s)) resources.complete_import_name(node_name, s) else Nil | 
| 72814 | 448 | "Bad theory import " + | 
| 449 | Markup.Path(import_name.node).markup(quote(import_name.toString)) + | |
| 450 | Position.here(pos) + Completion.report_theories(pos, completion) | |
| 59708 
aed304412e43
more markup, which helps to create missing imports;
 wenzelm parents: 
59706diff
changeset | 451 | } | 
| 72814 | 452 | Blobs_Info.errors(errors) | 
| 59702 
58dfaa369c11
hybrid use of command blobs: inlined errors and auxiliary files;
 wenzelm parents: 
59699diff
changeset | 453 | |
| 
58dfaa369c11
hybrid use of command blobs: inlined errors and auxiliary files;
 wenzelm parents: 
59699diff
changeset | 454 | // auxiliary files | 
| 
58dfaa369c11
hybrid use of command blobs: inlined errors and auxiliary files;
 wenzelm parents: 
59699diff
changeset | 455 | case _ => | 
| 72757 | 456 | val loaded_files = span.loaded_files(syntax) | 
| 59702 
58dfaa369c11
hybrid use of command blobs: inlined errors and auxiliary files;
 wenzelm parents: 
59699diff
changeset | 457 | val blobs = | 
| 72757 | 458 | loaded_files.files.map(file => | 
| 59702 
58dfaa369c11
hybrid use of command blobs: inlined errors and auxiliary files;
 wenzelm parents: 
59699diff
changeset | 459 |             (Exn.capture {
 | 
| 72747 
5f9d66155081
clarified theory keywords: loaded_files are determined statically in Scala, but ML needs to do it semantically;
 wenzelm parents: 
72745diff
changeset | 460 | val src_path = Path.explode(file) | 
| 76858 | 461 | val name = Document.Node.Name(resources.append_path(node_name.master_dir, src_path)) | 
| 72745 | 462 | val content = get_blob(name).map(blob => (blob.bytes.sha1_digest, blob.chunk)) | 
| 72747 
5f9d66155081
clarified theory keywords: loaded_files are determined statically in Scala, but ML needs to do it semantically;
 wenzelm parents: 
72745diff
changeset | 463 | Blob(name, src_path, content) | 
| 59702 
58dfaa369c11
hybrid use of command blobs: inlined errors and auxiliary files;
 wenzelm parents: 
59699diff
changeset | 464 | }).user_error) | 
| 72846 | 465 | Blobs_Info(blobs, index = loaded_files.index) | 
| 59702 
58dfaa369c11
hybrid use of command blobs: inlined errors and auxiliary files;
 wenzelm parents: 
59699diff
changeset | 466 | } | 
| 59689 
7968c57ea240
simplified Command.resolve_files in ML, using blobs_index from Scala;
 wenzelm parents: 
59684diff
changeset | 467 | } | 
| 34318 
c13e168a8ae6
original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
 wenzelm parents: diff
changeset | 468 | } | 
| 
c13e168a8ae6
original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
 wenzelm parents: diff
changeset | 469 | |
| 38361 | 470 | |
| 46712 | 471 | final class Command private( | 
| 75393 | 472 | val id: Document_ID.Command, | 
| 473 | val node_name: Document.Node.Name, | |
| 474 | val blobs_info: Command.Blobs_Info, | |
| 475 | val span: Command_Span.Span, | |
| 476 | val source: String, | |
| 477 | val init_results: Command.Results, | |
| 478 | val init_markups: Command.Markups | |
| 479 | ) {
 | |
| 73363 | 480 | override def toString: String = id.toString + "/" + span.kind.toString | 
| 34495 | 481 | |
| 57910 | 482 | |
| 483 | /* classification */ | |
| 484 | ||
| 57905 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: 
57904diff
changeset | 485 | def is_proper: Boolean = span.kind.isInstanceOf[Command_Span.Command_Span] | 
| 
c0c5652e796e
separate module Command_Span: mostly syntactic representation;
 wenzelm parents: 
57904diff
changeset | 486 | def is_ignored: Boolean = span.kind == Command_Span.Ignored_Span | 
| 57904 | 487 | |
| 488 | def is_undefined: Boolean = id == Document_ID.none | |
| 489 | val is_unparsed: Boolean = span.content.exists(_.is_unparsed) | |
| 490 | val is_unfinished: Boolean = span.content.exists(_.is_unfinished) | |
| 491 | ||
| 68323 | 492 | def potentially_initialized: Boolean = span.name == Thy_Header.THEORY | 
| 493 | ||
| 34859 | 494 | |
| 54519 
5fed81762406
maintain blobs within document state: digest + text in ML, digest-only in Scala;
 wenzelm parents: 
54517diff
changeset | 495 | /* blobs */ | 
| 
5fed81762406
maintain blobs within document state: digest + text in ML, digest-only in Scala;
 wenzelm parents: 
54517diff
changeset | 496 | |
| 72814 | 497 | def blobs: List[Exn.Result[Command.Blob]] = blobs_info.blobs | 
| 498 | def blobs_index: Int = blobs_info.index | |
| 59702 
58dfaa369c11
hybrid use of command blobs: inlined errors and auxiliary files;
 wenzelm parents: 
59699diff
changeset | 499 | |
| 78674 | 500 | def blobs_ok: Boolean = blobs.forall(Exn.is_res) | 
| 65335 | 501 | |
| 54530 
2c1440f70028
ranges of thy_load commands count as visible within perspective;
 wenzelm parents: 
54524diff
changeset | 502 | def blobs_names: List[Document.Node.Name] = | 
| 78592 | 503 | for (case Exn.Res(blob) <- blobs) yield blob.name | 
| 54530 
2c1440f70028
ranges of thy_load commands count as visible within perspective;
 wenzelm parents: 
54524diff
changeset | 504 | |
| 60916 
a6e2a667b0a8
resolve undefined blobs by default, e.g. relevant for ML debugger to avoid reset of breakpoints after reload;
 wenzelm parents: 
60215diff
changeset | 505 | def blobs_undefined: List[Document.Node.Name] = | 
| 78592 | 506 | for (case Exn.Res(blob) <- blobs if blob.content.isEmpty) yield blob.name | 
| 60916 
a6e2a667b0a8
resolve undefined blobs by default, e.g. relevant for ML debugger to avoid reset of breakpoints after reload;
 wenzelm parents: 
60215diff
changeset | 507 | |
| 57842 
8e4ae2db1849
more direct access to persistent blobs (see also 8953d4cc060a), avoiding fragile digest lookup from later version (which might have removed unused blobs already);
 wenzelm parents: 
57615diff
changeset | 508 | def blobs_defined: List[(Document.Node.Name, SHA1.Digest)] = | 
| 78592 | 509 | for (case Exn.Res(blob) <- blobs; (digest, _) <- blob.content) yield (blob.name, digest) | 
| 57842 
8e4ae2db1849
more direct access to persistent blobs (see also 8953d4cc060a), avoiding fragile digest lookup from later version (which might have removed unused blobs already);
 wenzelm parents: 
57615diff
changeset | 510 | |
| 
8e4ae2db1849
more direct access to persistent blobs (see also 8953d4cc060a), avoiding fragile digest lookup from later version (which might have removed unused blobs already);
 wenzelm parents: 
57615diff
changeset | 511 | def blobs_changed(doc_blobs: Document.Blobs): Boolean = | 
| 72745 | 512 |     blobs.exists({ case Exn.Res(blob) => doc_blobs.changed(blob.name) case _ => false })
 | 
| 54519 
5fed81762406
maintain blobs within document state: digest + text in ML, digest-only in Scala;
 wenzelm parents: 
54517diff
changeset | 513 | |
| 55432 
9c53198dbb1c
maintain multiple command chunks and markup trees: for main chunk and loaded files;
 wenzelm parents: 
55431diff
changeset | 514 | |
| 56462 
b64b0cb845fe
more explicit Command.Chunk types, less ooddities;
 wenzelm parents: 
56395diff
changeset | 515 | /* source chunks */ | 
| 55431 
e0f20a44ff9d
common Command.Chunk for command source and auxiliary files (static Symbol.Index without actual String content);
 wenzelm parents: 
55430diff
changeset | 516 | |
| 56746 | 517 | val chunk: Symbol.Text_Chunk = Symbol.Text_Chunk(source) | 
| 56473 | 518 | |
| 56746 | 519 | val chunks: Map[Symbol.Text_Chunk.Name, Symbol.Text_Chunk] = | 
| 520 | ((Symbol.Text_Chunk.Default -> chunk) :: | |
| 78592 | 521 | (for (case Exn.Res(blob) <- blobs; (_, file) <- blob.content) | 
| 72816 
ea4f86914cb2
support for PIDE markup for auxiliary files ("blobs");
 wenzelm parents: 
72814diff
changeset | 522 | yield blob.chunk_file -> file)).toMap | 
| 56473 | 523 | |
| 46813 | 524 | def length: Int = source.length | 
| 56473 | 525 | def range: Text.Range = chunk.range | 
| 46813 | 526 | |
| 68728 | 527 | val core_range: Text.Range = | 
| 57901 
e1abca2527da
more explicit type Span in Scala, according to ML version;
 wenzelm parents: 
57842diff
changeset | 528 | Text.Range(0, | 
| 76234 | 529 | span.content.reverseIterator.takeWhile(_.is_ignored).foldLeft(length)(_ - _.source.length)) | 
| 46813 | 530 | |
| 65522 | 531 | def source(range: Text.Range): String = range.substring(source) | 
| 38572 
0fe2c01ef7da
Command.State: accumulate markup reports uniformly;
 wenzelm parents: 
38564diff
changeset | 532 | |
| 38370 
8b15d0f98962
explicit Document.State value, instead of individual state variables in Session, Command, Document;
 wenzelm parents: 
38367diff
changeset | 533 | |
| 72946 | 534 | /* theory parents */ | 
| 535 | ||
| 536 | def theory_parents(resources: Resources): List[Document.Node.Name] = | |
| 537 |     if (span.name == Thy_Header.THEORY) {
 | |
| 538 |       try {
 | |
| 539 | val header = Thy_Header.read(node_name, span.content_reader) | |
| 540 | for ((s, _) <- header.imports) | |
| 541 |         yield {
 | |
| 542 |           try { resources.import_name(node_name, s) }
 | |
| 543 |           catch { case ERROR(_) => Document.Node.Name.empty }
 | |
| 544 | } | |
| 545 | } | |
| 546 |       catch { case ERROR(_) => Nil }
 | |
| 547 | } | |
| 548 | else Nil | |
| 549 | ||
| 550 | ||
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 551 | /* reported positions */ | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 552 | |
| 75393 | 553 | def reported_position( | 
| 554 | pos: Position.T | |
| 555 |   ) : Option[(Document_ID.Generic, Symbol.Text_Chunk.Name, Option[Symbol.Range])] = {
 | |
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 556 |     pos match {
 | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 557 | case Position.Id(id) => | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 558 | val chunk_name = | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 559 |           pos match {
 | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 560 | case Position.File(name) if name != node_name.node => | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 561 | Symbol.Text_Chunk.File(name) | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 562 | case _ => Symbol.Text_Chunk.Default | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 563 | } | 
| 72826 
fa5d8f486380
proper treatment of singleton Position.Offset within blob (amending cb9d5af781b4);
 wenzelm parents: 
72824diff
changeset | 564 | Some((id, chunk_name, Position.Range.unapply(pos))) | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 565 | case _ => None | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 566 | } | 
| 72826 
fa5d8f486380
proper treatment of singleton Position.Offset within blob (amending cb9d5af781b4);
 wenzelm parents: 
72824diff
changeset | 567 | } | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 568 | |
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 569 | def message_positions( | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 570 | self_id: Document_ID.Generic => Boolean, | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 571 | chunk_name: Symbol.Text_Chunk.Name, | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 572 | chunk: Symbol.Text_Chunk, | 
| 75393 | 573 | message: XML.Elem | 
| 574 |   ): Set[Text.Range] = {
 | |
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 575 | def elem(props: Properties.T, set: Set[Text.Range]): Set[Text.Range] = | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 576 |       reported_position(props) match {
 | 
| 72826 
fa5d8f486380
proper treatment of singleton Position.Offset within blob (amending cb9d5af781b4);
 wenzelm parents: 
72824diff
changeset | 577 | case Some((id, name, reported_range)) if self_id(id) && name == chunk_name => | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 578 | val opt_range = | 
| 72826 
fa5d8f486380
proper treatment of singleton Position.Offset within blob (amending cb9d5af781b4);
 wenzelm parents: 
72824diff
changeset | 579 |             reported_range orElse {
 | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 580 | if (name == Symbol.Text_Chunk.Default) | 
| 73115 
a8e5d7c9a834
discontinued odd absolute position (amending 85bcdd05c6d0, 1975f397eabb): it violates translation invariance of commands and may lead to redundant re-checking of PIDE document;
 wenzelm parents: 
73031diff
changeset | 581 | Position.Range.unapply(span.position) | 
| 72692 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 582 | else None | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 583 | } | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 584 |           opt_range match {
 | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 585 | case Some(symbol_range) => | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 586 |               chunk.incorporate(symbol_range) match {
 | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 587 | case Some(range) => set + range | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 588 | case _ => set | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 589 | } | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 590 | case None => set | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 591 | } | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 592 | case _ => set | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 593 | } | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 594 | def tree(set: Set[Text.Range], t: XML.Tree): Set[Text.Range] = | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 595 |       t match {
 | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 596 | case XML.Wrapped_Elem(Markup(name, props), _, body) => | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 597 | body.foldLeft(if (Rendering.position_elements(name)) elem(props, set) else set)(tree) | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 598 | case XML.Elem(Markup(name, props), body) => | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 599 | body.foldLeft(if (Rendering.position_elements(name)) elem(props, set) else set)(tree) | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 600 | case XML.Text(_) => set | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 601 | } | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 602 | |
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 603 | val set = tree(Set.empty, message) | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 604 | if (set.isEmpty) elem(message.markup.properties, set) | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 605 | else set | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 606 | } | 
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 607 | |
| 
22aeec526ffd
support for PIDE markup in batch build (inactive due to pide_reports=false);
 wenzelm parents: 
70780diff
changeset | 608 | |
| 38370 
8b15d0f98962
explicit Document.State value, instead of individual state variables in Session, Command, Document;
 wenzelm parents: 
38367diff
changeset | 609 | /* accumulated results */ | 
| 
8b15d0f98962
explicit Document.State value, instead of individual state variables in Session, Command, Document;
 wenzelm parents: 
38367diff
changeset | 610 | |
| 50501 
6f41f1646617
more careful handling of Dialog_Result, with active area and color feedback;
 wenzelm parents: 
50500diff
changeset | 611 | val init_state: Command.State = | 
| 72722 
ade53fbc6f03
clarified signature: initial markup is_empty, not init_markup;
 wenzelm parents: 
72709diff
changeset | 612 | Command.State(this, results = init_results, markups = init_markups) | 
| 52527 
dbac84eab3bc
separate exec_id assignment for Command.print states, without affecting result of eval;
 wenzelm parents: 
52524diff
changeset | 613 | |
| 
dbac84eab3bc
separate exec_id assignment for Command.print states, without affecting result of eval;
 wenzelm parents: 
52524diff
changeset | 614 | val empty_state: Command.State = Command.State(this) | 
| 34676 
9e725d34df7b
Command and Command_State handle results from prover as Accumulator
 immler@in.tum.de parents: 
34675diff
changeset | 615 | } |