| author | blanchet | 
| Thu, 14 Apr 2011 11:24:05 +0200 | |
| changeset 42353 | 7797efa897a1 | 
| parent 40572 | 2315c3daee74 | 
| child 43520 | cec9b95fa35d | 
| permissions | -rw-r--r-- | 
| 36676 | 1 | /* Title: Pure/PIDE/command.scala | 
| 2 | Author: Fabian Immler, TU Munich | |
| 3 | Author: Makarius | |
| 4 | ||
| 5 | Prover commands with semantic state. | |
| 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 | ||
| 34637 | 14 | object Command | 
| 15 | {
 | |
| 38361 | 16 | /** accumulated results from prover **/ | 
| 17 | ||
| 38362 | 18 | case class State( | 
| 38361 | 19 | val command: Command, | 
| 38872 | 20 | val status: List[Markup] = Nil, | 
| 21 | val results: SortedMap[Long, XML.Tree] = SortedMap.empty, | |
| 22 | val markup: Markup_Tree = Markup_Tree.empty) | |
| 38361 | 23 |   {
 | 
| 24 | /* content */ | |
| 25 | ||
| 38714 | 26 | def add_status(st: Markup): State = copy(status = st :: status) | 
| 27 | def add_markup(info: Text.Info[Any]): State = copy(markup = markup + info) | |
| 38872 | 28 | def add_result(serial: Long, result: XML.Tree): State = | 
| 29 | copy(results = results + (serial -> result)) | |
| 38361 | 30 | |
| 38658 | 31 | def root_info: Text.Info[Any] = | 
| 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 | 32 | new Text.Info(command.range, | 
| 38658 | 33 | XML.Elem(Markup(Markup.STATUS, Nil), status.reverse.map(XML.Elem(_, Nil)))) | 
| 34 | def root_markup: Markup_Tree = markup + root_info | |
| 38361 | 35 | |
| 36 | ||
| 37 | /* message dispatch */ | |
| 38 | ||
| 38872 | 39 | def accumulate(message: XML.Elem): Command.State = | 
| 38361 | 40 |       message match {
 | 
| 38714 | 41 | case XML.Elem(Markup(Markup.STATUS, _), msgs) => | 
| 42 | (this /: msgs)((state, msg) => | |
| 43 |             msg match {
 | |
| 44 | case XML.Elem(markup, Nil) => state.add_status(markup) | |
| 45 |               case _ => System.err.println("Ignored status message: " + msg); state
 | |
| 46 | }) | |
| 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 | 47 | |
| 38572 
0fe2c01ef7da
Command.State: accumulate markup reports uniformly;
 wenzelm parents: 
38564diff
changeset | 48 | case XML.Elem(Markup(Markup.REPORT, _), msgs) => | 
| 
0fe2c01ef7da
Command.State: accumulate markup reports uniformly;
 wenzelm parents: 
38564diff
changeset | 49 | (this /: msgs)((state, msg) => | 
| 
0fe2c01ef7da
Command.State: accumulate markup reports uniformly;
 wenzelm parents: 
38564diff
changeset | 50 |             msg match {
 | 
| 39173 
ed3946086358
Command.State.accumulate: check actual source range;
 wenzelm parents: 
39172diff
changeset | 51 | case XML.Elem(Markup(name, atts @ Position.Id_Range(id, raw_range)), args) | 
| 
ed3946086358
Command.State.accumulate: check actual source range;
 wenzelm parents: 
39172diff
changeset | 52 | if id == command.id && command.range.contains(command.decode(raw_range)) => | 
| 
ed3946086358
Command.State.accumulate: check actual source range;
 wenzelm parents: 
39172diff
changeset | 53 | val range = command.decode(raw_range) | 
| 38872 | 54 | val props = Position.purge(atts) | 
| 39173 
ed3946086358
Command.State.accumulate: check actual source range;
 wenzelm parents: 
39172diff
changeset | 55 | val info = Text.Info[Any](range, XML.Elem(Markup(name, props), args)) | 
| 38723 | 56 | state.add_markup(info) | 
| 40572 | 57 | case _ => | 
| 58 |                 // FIXME System.err.println("Ignored report message: " + msg)
 | |
| 59 | state | |
| 38361 | 60 | }) | 
| 38872 | 61 | case XML.Elem(Markup(name, atts), body) => | 
| 62 |           atts match {
 | |
| 63 | case Markup.Serial(i) => | |
| 38887 
1261481ef5e5
Command.State: add reported positions to markup tree, according main message position or Markup.binding/entity/report occurrences in body;
 wenzelm parents: 
38877diff
changeset | 64 | val result = XML.Elem(Markup(name, Position.purge(atts)), body) | 
| 39622 
53365ba766ac
Command.accumulate: refrain from adding tracing messages to markup tree -- potential scalability problem;
 wenzelm parents: 
39441diff
changeset | 65 | val st0 = add_result(i, result) | 
| 39441 
4110cc1b8f9f
allow embedded reports in regular prover messages, to avoid side-effects for errors for example;
 wenzelm parents: 
39173diff
changeset | 66 | val st1 = | 
| 39622 
53365ba766ac
Command.accumulate: refrain from adding tracing messages to markup tree -- potential scalability problem;
 wenzelm parents: 
39441diff
changeset | 67 | if (Isar_Document.is_tracing(message)) st0 | 
| 
53365ba766ac
Command.accumulate: refrain from adding tracing messages to markup tree -- potential scalability problem;
 wenzelm parents: 
39441diff
changeset | 68 | else | 
| 
53365ba766ac
Command.accumulate: refrain from adding tracing messages to markup tree -- potential scalability problem;
 wenzelm parents: 
39441diff
changeset | 69 | (st0 /: Isar_Document.message_positions(command, message))( | 
| 
53365ba766ac
Command.accumulate: refrain from adding tracing messages to markup tree -- potential scalability problem;
 wenzelm parents: 
39441diff
changeset | 70 | (st, range) => st.add_markup(Text.Info(range, result))) | 
| 
53365ba766ac
Command.accumulate: refrain from adding tracing messages to markup tree -- potential scalability problem;
 wenzelm parents: 
39441diff
changeset | 71 | val st2 = (st1 /: Isar_Document.message_reports(message))(_ accumulate _) | 
| 
53365ba766ac
Command.accumulate: refrain from adding tracing messages to markup tree -- potential scalability problem;
 wenzelm parents: 
39441diff
changeset | 72 | st2 | 
| 38872 | 73 |             case _ => System.err.println("Ignored message without serial number: " + message); this
 | 
| 74 | } | |
| 38361 | 75 | } | 
| 76 | } | |
| 38367 | 77 | |
| 78 | ||
| 40454 
2516ea25a54b
some support for nested source structure, based on section headings;
 wenzelm parents: 
39622diff
changeset | 79 | /* dummy commands */ | 
| 38367 | 80 | |
| 40454 
2516ea25a54b
some support for nested source structure, based on section headings;
 wenzelm parents: 
39622diff
changeset | 81 | def unparsed(source: String): Command = | 
| 38367 | 82 | new Command(Document.NO_ID, List(Token(Token.Kind.UNPARSED, source))) | 
| 40454 
2516ea25a54b
some support for nested source structure, based on section headings;
 wenzelm parents: 
39622diff
changeset | 83 | |
| 
2516ea25a54b
some support for nested source structure, based on section headings;
 wenzelm parents: 
39622diff
changeset | 84 | def span(toks: List[Token]): Command = | 
| 
2516ea25a54b
some support for nested source structure, based on section headings;
 wenzelm parents: 
39622diff
changeset | 85 | new Command(Document.NO_ID, toks) | 
| 34318 
c13e168a8ae6
original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
 wenzelm parents: diff
changeset | 86 | } | 
| 
c13e168a8ae6
original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
 wenzelm parents: diff
changeset | 87 | |
| 38361 | 88 | |
| 34697 | 89 | class Command( | 
| 38150 
67fc24df3721
simplified/refined document model: collection of named nodes, without proper dependencies yet;
 wenzelm parents: 
37373diff
changeset | 90 | val id: Document.Command_ID, | 
| 38373 | 91 | val span: List[Token]) | 
| 34451 | 92 | {
 | 
| 34859 | 93 | /* classification */ | 
| 34500 
384427c750c8
state_results: separate buffer for messages from running command;
 wenzelm parents: 
34497diff
changeset | 94 | |
| 36012 | 95 | def is_command: Boolean = !span.isEmpty && span.head.is_command | 
| 34865 | 96 | def is_ignored: Boolean = span.forall(_.is_ignored) | 
| 34859 | 97 | def is_malformed: Boolean = !is_command && !is_ignored | 
| 98 | ||
| 38367 | 99 | def is_unparsed = id == Document.NO_ID | 
| 100 | ||
| 36012 | 101 | def name: String = if (is_command) span.head.content else "" | 
| 37129 | 102 | override def toString = | 
| 37373 
25078ba44436
tuned Command.toString -- preserving uniqueness allows the Scala toplevel to print Linear_Set[Command] results without crashing;
 wenzelm parents: 
37197diff
changeset | 103 | id + "/" + (if (is_command) name else if (is_ignored) "IGNORED" else "MALFORMED") | 
| 34495 | 104 | |
| 34859 | 105 | |
| 106 | /* source text */ | |
| 34451 | 107 | |
| 34859 | 108 | val source: String = span.map(_.source).mkString | 
| 38426 | 109 | def source(range: Text.Range): String = source.substring(range.start, range.stop) | 
| 34859 | 110 | def length: Int = source.length | 
| 38572 
0fe2c01ef7da
Command.State: accumulate markup reports uniformly;
 wenzelm parents: 
38564diff
changeset | 111 | |
| 38877 | 112 | val newlines = | 
| 113 |     (0 /: Symbol.iterator(source)) {
 | |
| 114 | case (n, s) => if (Symbol.is_physical_newline(s)) n + 1 else n } | |
| 115 | ||
| 38479 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 wenzelm parents: 
38476diff
changeset | 116 | val range: Text.Range = Text.Range(0, length) | 
| 34855 
81d0410dc3ac
iterators for ranges of commands/starts -- avoid extra array per document;
 wenzelm parents: 
34835diff
changeset | 117 | |
| 34859 | 118 | lazy val symbol_index = new Symbol.Index(source) | 
| 38579 | 119 | def decode(i: Text.Offset): Text.Offset = symbol_index.decode(i) | 
| 120 | def decode(r: Text.Range): Text.Range = symbol_index.decode(r) | |
| 38370 
8b15d0f98962
explicit Document.State value, instead of individual state variables in Session, Command, Document;
 wenzelm parents: 
38367diff
changeset | 121 | |
| 
8b15d0f98962
explicit Document.State value, instead of individual state variables in Session, Command, Document;
 wenzelm parents: 
38367diff
changeset | 122 | |
| 
8b15d0f98962
explicit Document.State value, instead of individual state variables in Session, Command, Document;
 wenzelm parents: 
38367diff
changeset | 123 | /* accumulated results */ | 
| 
8b15d0f98962
explicit Document.State value, instead of individual state variables in Session, Command, Document;
 wenzelm parents: 
38367diff
changeset | 124 | |
| 38872 | 125 | 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 | 126 | } |