| author | wenzelm | 
| Tue, 18 Sep 2012 13:18:45 +0200 | |
| changeset 49414 | d7b5fb2e9ca2 | 
| parent 49359 | c1262d7389fb | 
| child 49416 | 1053a564dd25 | 
| 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: 
34865 
diff
changeset
 | 
8  | 
package isabelle  | 
| 
34318
 
c13e168a8ae6
original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
 
wenzelm 
parents:  
diff
changeset
 | 
9  | 
|
| 
43520
 
cec9b95fa35d
explicit import java.lang.System to prevent odd scope problems;
 
wenzelm 
parents: 
40572 
diff
changeset
 | 
10  | 
import java.lang.System  | 
| 34451 | 11  | 
|
| 45644 | 12  | 
import scala.collection.mutable  | 
| 38872 | 13  | 
import scala.collection.immutable.SortedMap  | 
14  | 
||
15  | 
||
| 34637 | 16  | 
object Command  | 
17  | 
{
 | 
|
| 38361 | 18  | 
/** accumulated results from prover **/  | 
19  | 
||
| 43714 | 20  | 
sealed case class State(  | 
| 38361 | 21  | 
val command: Command,  | 
| 38872 | 22  | 
val status: List[Markup] = Nil,  | 
23  | 
val results: SortedMap[Long, XML.Tree] = SortedMap.empty,  | 
|
24  | 
val markup: Markup_Tree = Markup_Tree.empty)  | 
|
| 38361 | 25  | 
  {
 | 
| 
46152
 
793cecd4ffc0
accumulate status as regular markup for command range;
 
wenzelm 
parents: 
45709 
diff
changeset
 | 
26  | 
/* accumulate content */  | 
| 38361 | 27  | 
|
| 
46152
 
793cecd4ffc0
accumulate status as regular markup for command range;
 
wenzelm 
parents: 
45709 
diff
changeset
 | 
28  | 
private def add_status(st: Markup): State = copy(status = st :: status)  | 
| 
 
793cecd4ffc0
accumulate status as regular markup for command range;
 
wenzelm 
parents: 
45709 
diff
changeset
 | 
29  | 
private def add_markup(m: Text.Markup): State = copy(markup = markup + m)  | 
| 38361 | 30  | 
|
| 
46152
 
793cecd4ffc0
accumulate status as regular markup for command range;
 
wenzelm 
parents: 
45709 
diff
changeset
 | 
31  | 
def + (message: XML.Elem): Command.State =  | 
| 38361 | 32  | 
      message match {
 | 
| 45666 | 33  | 
case XML.Elem(Markup(Isabelle_Markup.STATUS, _), msgs) =>  | 
| 38714 | 34  | 
(this /: msgs)((state, msg) =>  | 
35  | 
            msg match {
 | 
|
| 
46152
 
793cecd4ffc0
accumulate status as regular markup for command range;
 
wenzelm 
parents: 
45709 
diff
changeset
 | 
36  | 
case elem @ XML.Elem(markup, Nil) =>  | 
| 
46910
 
3e068ef04b42
clarified command state -- markup within proper_range, excluding trailing whitespace;
 
wenzelm 
parents: 
46813 
diff
changeset
 | 
37  | 
state.add_status(markup).add_markup(Text.Info(command.proper_range, elem))  | 
| 
46152
 
793cecd4ffc0
accumulate status as regular markup for command range;
 
wenzelm 
parents: 
45709 
diff
changeset
 | 
38  | 
|
| 38714 | 39  | 
              case _ => System.err.println("Ignored status message: " + msg); state
 | 
40  | 
})  | 
|
| 
38581
 
d503a0912e14
simplified Command.status again, reverting most of e5eed57913d0 (note that more complex information can be represented with full markup reports);
 
wenzelm 
parents: 
38579 
diff
changeset
 | 
41  | 
|
| 45666 | 42  | 
case XML.Elem(Markup(Isabelle_Markup.REPORT, _), msgs) =>  | 
| 
38572
 
0fe2c01ef7da
Command.State: accumulate markup reports uniformly;
 
wenzelm 
parents: 
38564 
diff
changeset
 | 
43  | 
(this /: msgs)((state, msg) =>  | 
| 
 
0fe2c01ef7da
Command.State: accumulate markup reports uniformly;
 
wenzelm 
parents: 
38564 
diff
changeset
 | 
44  | 
            msg match {
 | 
| 
39173
 
ed3946086358
Command.State.accumulate: check actual source range;
 
wenzelm 
parents: 
39172 
diff
changeset
 | 
45  | 
case XML.Elem(Markup(name, atts @ Position.Id_Range(id, raw_range)), args)  | 
| 
 
ed3946086358
Command.State.accumulate: check actual source range;
 
wenzelm 
parents: 
39172 
diff
changeset
 | 
46  | 
if id == command.id && command.range.contains(command.decode(raw_range)) =>  | 
| 
 
ed3946086358
Command.State.accumulate: check actual source range;
 
wenzelm 
parents: 
39172 
diff
changeset
 | 
47  | 
val range = command.decode(raw_range)  | 
| 38872 | 48  | 
val props = Position.purge(atts)  | 
| 45455 | 49  | 
val info: Text.Markup = Text.Info(range, XML.Elem(Markup(name, props), args))  | 
| 38723 | 50  | 
state.add_markup(info)  | 
| 
49037
 
d7a1973b063c
more markup for failed goal forks, reusing "bad";
 
wenzelm 
parents: 
48922 
diff
changeset
 | 
51  | 
case XML.Elem(Markup(name, atts), args) =>  | 
| 
 
d7a1973b063c
more markup for failed goal forks, reusing "bad";
 
wenzelm 
parents: 
48922 
diff
changeset
 | 
52  | 
val range = command.proper_range  | 
| 
 
d7a1973b063c
more markup for failed goal forks, reusing "bad";
 
wenzelm 
parents: 
48922 
diff
changeset
 | 
53  | 
val props = Position.purge(atts)  | 
| 
 
d7a1973b063c
more markup for failed goal forks, reusing "bad";
 
wenzelm 
parents: 
48922 
diff
changeset
 | 
54  | 
val info: Text.Markup = Text.Info(range, XML.Elem(Markup(name, props), args))  | 
| 
 
d7a1973b063c
more markup for failed goal forks, reusing "bad";
 
wenzelm 
parents: 
48922 
diff
changeset
 | 
55  | 
state.add_markup(info)  | 
| 40572 | 56  | 
case _ =>  | 
57  | 
                // FIXME System.err.println("Ignored report message: " + msg)
 | 
|
58  | 
state  | 
|
| 38361 | 59  | 
})  | 
| 38872 | 60  | 
case XML.Elem(Markup(name, atts), body) =>  | 
61  | 
          atts match {
 | 
|
| 45666 | 62  | 
case Isabelle_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: 
38877 
diff
changeset
 | 
63  | 
val result = XML.Elem(Markup(name, Position.purge(atts)), body)  | 
| 
46152
 
793cecd4ffc0
accumulate status as regular markup for command range;
 
wenzelm 
parents: 
45709 
diff
changeset
 | 
64  | 
val st0 = copy(results = results + (i -> result))  | 
| 
39441
 
4110cc1b8f9f
allow embedded reports in regular prover messages, to avoid side-effects for errors for example;
 
wenzelm 
parents: 
39173 
diff
changeset
 | 
65  | 
val st1 =  | 
| 
45709
 
87017fcbad83
clarified modules (again) -- NB: both Document and Protocol are specific to this particular prover;
 
wenzelm 
parents: 
45672 
diff
changeset
 | 
66  | 
if (Protocol.is_tracing(message)) st0  | 
| 
39622
 
53365ba766ac
Command.accumulate: refrain from adding tracing messages to markup tree -- potential scalability problem;
 
wenzelm 
parents: 
39441 
diff
changeset
 | 
67  | 
else  | 
| 
45709
 
87017fcbad83
clarified modules (again) -- NB: both Document and Protocol are specific to this particular prover;
 
wenzelm 
parents: 
45672 
diff
changeset
 | 
68  | 
(st0 /: Protocol.message_positions(command, message))(  | 
| 
39622
 
53365ba766ac
Command.accumulate: refrain from adding tracing messages to markup tree -- potential scalability problem;
 
wenzelm 
parents: 
39441 
diff
changeset
 | 
69  | 
(st, range) => st.add_markup(Text.Info(range, result)))  | 
| 
46152
 
793cecd4ffc0
accumulate status as regular markup for command range;
 
wenzelm 
parents: 
45709 
diff
changeset
 | 
70  | 
val st2 = (st1 /: Protocol.message_reports(message))(_ + _)  | 
| 
39622
 
53365ba766ac
Command.accumulate: refrain from adding tracing messages to markup tree -- potential scalability problem;
 
wenzelm 
parents: 
39441 
diff
changeset
 | 
71  | 
st2  | 
| 38872 | 72  | 
            case _ => System.err.println("Ignored message without serial number: " + message); this
 | 
73  | 
}  | 
|
| 38361 | 74  | 
}  | 
75  | 
}  | 
|
| 38367 | 76  | 
|
77  | 
||
| 45644 | 78  | 
/* make commands */  | 
79  | 
||
| 48745 | 80  | 
type Span = List[Token]  | 
81  | 
||
| 49414 | 82  | 
def apply(id: Document.Command_ID, node_name: Document.Node.Name,  | 
83  | 
span: Span, markup: Markup_Tree): Command =  | 
|
| 45644 | 84  | 
  {
 | 
85  | 
val source: String =  | 
|
| 48745 | 86  | 
      span match {
 | 
| 45644 | 87  | 
case List(tok) => tok.source  | 
| 48745 | 88  | 
case _ => span.map(_.source).mkString  | 
| 45644 | 89  | 
}  | 
90  | 
||
| 48745 | 91  | 
val span1 = new mutable.ListBuffer[Token]  | 
| 45644 | 92  | 
var i = 0  | 
| 48745 | 93  | 
    for (Token(kind, s) <- span) {
 | 
| 45644 | 94  | 
val n = s.length  | 
95  | 
val s1 = source.substring(i, i + n)  | 
|
| 48745 | 96  | 
span1 += Token(kind, s1)  | 
| 45644 | 97  | 
i += n  | 
98  | 
}  | 
|
99  | 
||
| 49414 | 100  | 
new Command(id, node_name, span1.toList, source, markup)  | 
| 45644 | 101  | 
}  | 
102  | 
||
| 49414 | 103  | 
val empty = Command(Document.no_id, Document.Node.Name.empty, Nil, Markup_Tree.empty)  | 
104  | 
||
105  | 
def unparsed(id: Document.Command_ID, source: String, markup: Markup_Tree): Command =  | 
|
106  | 
Command(id, Document.Node.Name.empty, List(Token(Token.Kind.UNPARSED, source)), markup)  | 
|
107  | 
||
108  | 
def unparsed(source: String): Command = unparsed(Document.no_id, source, Markup_Tree.empty)  | 
|
| 44384 | 109  | 
|
| 49414 | 110  | 
def rich_text(id: Document.Command_ID, body: XML.Body): Command =  | 
111  | 
  {
 | 
|
112  | 
val text = XML.content(body).mkString  | 
|
113  | 
val markup = Markup_Tree.empty // FIXME  | 
|
114  | 
unparsed(id, text, markup)  | 
|
115  | 
}  | 
|
| 
49359
 
c1262d7389fb
refined output panel: more value-oriented approach to update and caret focus;
 
wenzelm 
parents: 
49037 
diff
changeset
 | 
116  | 
|
| 44384 | 117  | 
|
118  | 
/* perspective */  | 
|
119  | 
||
| 44474 | 120  | 
object Perspective  | 
121  | 
  {
 | 
|
122  | 
val empty: Perspective = Perspective(Nil)  | 
|
123  | 
}  | 
|
| 
44385
 
e7fdb008aa7d
propagate editor perspective through document model;
 
wenzelm 
parents: 
44384 
diff
changeset
 | 
124  | 
|
| 44474 | 125  | 
sealed case class Perspective(commands: List[Command]) // visible commands in canonical order  | 
| 
44385
 
e7fdb008aa7d
propagate editor perspective through document model;
 
wenzelm 
parents: 
44384 
diff
changeset
 | 
126  | 
  {
 | 
| 44474 | 127  | 
def same(that: Perspective): Boolean =  | 
128  | 
    {
 | 
|
129  | 
val cmds1 = this.commands  | 
|
130  | 
val cmds2 = that.commands  | 
|
| 
48754
 
c2c1e5944536
clarified undefined, unparsed, unfinished command spans;
 
wenzelm 
parents: 
48745 
diff
changeset
 | 
131  | 
require(!cmds1.exists(_.is_undefined))  | 
| 
 
c2c1e5944536
clarified undefined, unparsed, unfinished command spans;
 
wenzelm 
parents: 
48745 
diff
changeset
 | 
132  | 
require(!cmds2.exists(_.is_undefined))  | 
| 44474 | 133  | 
cmds1.length == cmds2.length &&  | 
134  | 
        (cmds1.iterator zip cmds2.iterator).forall({ case (c1, c2) => c1.id == c2.id })
 | 
|
135  | 
}  | 
|
| 
44385
 
e7fdb008aa7d
propagate editor perspective through document model;
 
wenzelm 
parents: 
44384 
diff
changeset
 | 
136  | 
}  | 
| 
34318
 
c13e168a8ae6
original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
 
wenzelm 
parents:  
diff
changeset
 | 
137  | 
}  | 
| 
 
c13e168a8ae6
original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
 
wenzelm 
parents:  
diff
changeset
 | 
138  | 
|
| 38361 | 139  | 
|
| 46712 | 140  | 
final class Command private(  | 
| 
38150
 
67fc24df3721
simplified/refined document model: collection of named nodes, without proper dependencies yet;
 
wenzelm 
parents: 
37373 
diff
changeset
 | 
141  | 
val id: Document.Command_ID,  | 
| 44615 | 142  | 
val node_name: Document.Node.Name,  | 
| 48745 | 143  | 
val span: Command.Span,  | 
| 49414 | 144  | 
val source: String,  | 
145  | 
val init_markup: Markup_Tree)  | 
|
| 34451 | 146  | 
{
 | 
| 34859 | 147  | 
/* classification */  | 
| 
34500
 
384427c750c8
state_results: separate buffer for messages from running command;
 
wenzelm 
parents: 
34497 
diff
changeset
 | 
148  | 
|
| 
48754
 
c2c1e5944536
clarified undefined, unparsed, unfinished command spans;
 
wenzelm 
parents: 
48745 
diff
changeset
 | 
149  | 
def is_undefined: Boolean = id == Document.no_id  | 
| 
 
c2c1e5944536
clarified undefined, unparsed, unfinished command spans;
 
wenzelm 
parents: 
48745 
diff
changeset
 | 
150  | 
val is_unparsed: Boolean = span.exists(_.is_unparsed)  | 
| 
 
c2c1e5944536
clarified undefined, unparsed, unfinished command spans;
 
wenzelm 
parents: 
48745 
diff
changeset
 | 
151  | 
val is_unfinished: Boolean = span.exists(_.is_unfinished)  | 
| 
44385
 
e7fdb008aa7d
propagate editor perspective through document model;
 
wenzelm 
parents: 
44384 
diff
changeset
 | 
152  | 
|
| 48599 | 153  | 
val is_ignored: Boolean = !span.exists(_.is_proper)  | 
| 
48754
 
c2c1e5944536
clarified undefined, unparsed, unfinished command spans;
 
wenzelm 
parents: 
48745 
diff
changeset
 | 
154  | 
val is_malformed: Boolean = !is_ignored && (!span.head.is_command || span.exists(_.is_error))  | 
| 
47012
 
0e246130486b
clarified command span classification: strict Command.is_command, permissive Command.name;
 
wenzelm 
parents: 
46910 
diff
changeset
 | 
155  | 
def is_command: Boolean = !is_ignored && !is_malformed  | 
| 34859 | 156  | 
|
| 
47012
 
0e246130486b
clarified command span classification: strict Command.is_command, permissive Command.name;
 
wenzelm 
parents: 
46910 
diff
changeset
 | 
157  | 
def name: String =  | 
| 48718 | 158  | 
    span.find(_.is_command) match { case Some(tok) => tok.source case _ => "" }
 | 
| 
47012
 
0e246130486b
clarified command span classification: strict Command.is_command, permissive Command.name;
 
wenzelm 
parents: 
46910 
diff
changeset
 | 
159  | 
|
| 37129 | 160  | 
override def toString =  | 
| 
37373
 
25078ba44436
tuned Command.toString -- preserving uniqueness allows the Scala toplevel to print Linear_Set[Command] results without crashing;
 
wenzelm 
parents: 
37197 
diff
changeset
 | 
161  | 
id + "/" + (if (is_command) name else if (is_ignored) "IGNORED" else "MALFORMED")  | 
| 34495 | 162  | 
|
| 34859 | 163  | 
|
164  | 
/* source text */  | 
|
| 34451 | 165  | 
|
| 46813 | 166  | 
def length: Int = source.length  | 
167  | 
val range: Text.Range = Text.Range(0, length)  | 
|
168  | 
||
169  | 
val proper_range: Text.Range =  | 
|
| 
47459
 
373e456149cc
include trailing comments in proper_command range;
 
wenzelm 
parents: 
47012 
diff
changeset
 | 
170  | 
Text.Range(0, (length /: span.reverse.iterator.takeWhile(_.is_space))(_ - _.source.length))  | 
| 46813 | 171  | 
|
| 38426 | 172  | 
def source(range: Text.Range): String = source.substring(range.start, range.stop)  | 
| 
38572
 
0fe2c01ef7da
Command.State: accumulate markup reports uniformly;
 
wenzelm 
parents: 
38564 
diff
changeset
 | 
173  | 
|
| 34859 | 174  | 
lazy val symbol_index = new Symbol.Index(source)  | 
| 38579 | 175  | 
def decode(i: Text.Offset): Text.Offset = symbol_index.decode(i)  | 
176  | 
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: 
38367 
diff
changeset
 | 
177  | 
|
| 
 
8b15d0f98962
explicit Document.State value, instead of individual state variables in Session, Command, Document;
 
wenzelm 
parents: 
38367 
diff
changeset
 | 
178  | 
|
| 
 
8b15d0f98962
explicit Document.State value, instead of individual state variables in Session, Command, Document;
 
wenzelm 
parents: 
38367 
diff
changeset
 | 
179  | 
/* accumulated results */  | 
| 
 
8b15d0f98962
explicit Document.State value, instead of individual state variables in Session, Command, Document;
 
wenzelm 
parents: 
38367 
diff
changeset
 | 
180  | 
|
| 49414 | 181  | 
val init_state: Command.State = Command.State(this, markup = init_markup)  | 
| 
34676
 
9e725d34df7b
Command and Command_State handle results from prover as Accumulator
 
immler@in.tum.de 
parents: 
34675 
diff
changeset
 | 
182  | 
}  |