| author | wenzelm | 
| Wed, 31 Aug 2011 15:41:22 +0200 | |
| changeset 44607 | 274eff0ea12e | 
| parent 44474 | 681447a9ffe5 | 
| child 44615 | a4ff8a787202 | 
| 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  | 
|
| 38872 | 12  | 
import scala.collection.immutable.SortedMap  | 
13  | 
||
14  | 
||
| 34637 | 15  | 
object Command  | 
16  | 
{
 | 
|
| 38361 | 17  | 
/** accumulated results from prover **/  | 
18  | 
||
| 43714 | 19  | 
sealed case class State(  | 
| 38361 | 20  | 
val command: Command,  | 
| 38872 | 21  | 
val status: List[Markup] = Nil,  | 
22  | 
val results: SortedMap[Long, XML.Tree] = SortedMap.empty,  | 
|
23  | 
val markup: Markup_Tree = Markup_Tree.empty)  | 
|
| 38361 | 24  | 
  {
 | 
25  | 
/* content */  | 
|
26  | 
||
| 38714 | 27  | 
def add_status(st: Markup): State = copy(status = st :: status)  | 
28  | 
def add_markup(info: Text.Info[Any]): State = copy(markup = markup + info)  | 
|
| 38872 | 29  | 
def add_result(serial: Long, result: XML.Tree): State =  | 
30  | 
copy(results = results + (serial -> result))  | 
|
| 38361 | 31  | 
|
| 38658 | 32  | 
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: 
38579 
diff
changeset
 | 
33  | 
new Text.Info(command.range,  | 
| 38658 | 34  | 
XML.Elem(Markup(Markup.STATUS, Nil), status.reverse.map(XML.Elem(_, Nil))))  | 
35  | 
def root_markup: Markup_Tree = markup + root_info  | 
|
| 38361 | 36  | 
|
37  | 
||
38  | 
/* message dispatch */  | 
|
39  | 
||
| 38872 | 40  | 
def accumulate(message: XML.Elem): Command.State =  | 
| 38361 | 41  | 
      message match {
 | 
| 38714 | 42  | 
case XML.Elem(Markup(Markup.STATUS, _), msgs) =>  | 
43  | 
(this /: msgs)((state, msg) =>  | 
|
44  | 
            msg match {
 | 
|
45  | 
case XML.Elem(markup, Nil) => state.add_status(markup)  | 
|
46  | 
              case _ => System.err.println("Ignored status message: " + msg); state
 | 
|
47  | 
})  | 
|
| 
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
 | 
48  | 
|
| 
38572
 
0fe2c01ef7da
Command.State: accumulate markup reports uniformly;
 
wenzelm 
parents: 
38564 
diff
changeset
 | 
49  | 
case XML.Elem(Markup(Markup.REPORT, _), msgs) =>  | 
| 
 
0fe2c01ef7da
Command.State: accumulate markup reports uniformly;
 
wenzelm 
parents: 
38564 
diff
changeset
 | 
50  | 
(this /: msgs)((state, msg) =>  | 
| 
 
0fe2c01ef7da
Command.State: accumulate markup reports uniformly;
 
wenzelm 
parents: 
38564 
diff
changeset
 | 
51  | 
            msg match {
 | 
| 
39173
 
ed3946086358
Command.State.accumulate: check actual source range;
 
wenzelm 
parents: 
39172 
diff
changeset
 | 
52  | 
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
 | 
53  | 
if id == command.id && command.range.contains(command.decode(raw_range)) =>  | 
| 
 
ed3946086358
Command.State.accumulate: check actual source range;
 
wenzelm 
parents: 
39172 
diff
changeset
 | 
54  | 
val range = command.decode(raw_range)  | 
| 38872 | 55  | 
val props = Position.purge(atts)  | 
| 
39173
 
ed3946086358
Command.State.accumulate: check actual source range;
 
wenzelm 
parents: 
39172 
diff
changeset
 | 
56  | 
val info = Text.Info[Any](range, XML.Elem(Markup(name, props), args))  | 
| 38723 | 57  | 
state.add_markup(info)  | 
| 40572 | 58  | 
case _ =>  | 
59  | 
                // FIXME System.err.println("Ignored report message: " + msg)
 | 
|
60  | 
state  | 
|
| 38361 | 61  | 
})  | 
| 38872 | 62  | 
case XML.Elem(Markup(name, atts), body) =>  | 
63  | 
          atts match {
 | 
|
64  | 
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: 
38877 
diff
changeset
 | 
65  | 
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: 
39441 
diff
changeset
 | 
66  | 
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: 
39173 
diff
changeset
 | 
67  | 
val st1 =  | 
| 
39622
 
53365ba766ac
Command.accumulate: refrain from adding tracing messages to markup tree -- potential scalability problem;
 
wenzelm 
parents: 
39441 
diff
changeset
 | 
68  | 
if (Isar_Document.is_tracing(message)) st0  | 
| 
 
53365ba766ac
Command.accumulate: refrain from adding tracing messages to markup tree -- potential scalability problem;
 
wenzelm 
parents: 
39441 
diff
changeset
 | 
69  | 
else  | 
| 
 
53365ba766ac
Command.accumulate: refrain from adding tracing messages to markup tree -- potential scalability problem;
 
wenzelm 
parents: 
39441 
diff
changeset
 | 
70  | 
(st0 /: Isar_Document.message_positions(command, message))(  | 
| 
 
53365ba766ac
Command.accumulate: refrain from adding tracing messages to markup tree -- potential scalability problem;
 
wenzelm 
parents: 
39441 
diff
changeset
 | 
71  | 
(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: 
39441 
diff
changeset
 | 
72  | 
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: 
39441 
diff
changeset
 | 
73  | 
st2  | 
| 38872 | 74  | 
            case _ => System.err.println("Ignored message without serial number: " + message); this
 | 
75  | 
}  | 
|
| 38361 | 76  | 
}  | 
77  | 
}  | 
|
| 38367 | 78  | 
|
79  | 
||
| 
40454
 
2516ea25a54b
some support for nested source structure, based on section headings;
 
wenzelm 
parents: 
39622 
diff
changeset
 | 
80  | 
/* dummy commands */  | 
| 38367 | 81  | 
|
| 
40454
 
2516ea25a54b
some support for nested source structure, based on section headings;
 
wenzelm 
parents: 
39622 
diff
changeset
 | 
82  | 
def unparsed(source: String): Command =  | 
| 
44607
 
274eff0ea12e
maintain name of *the* enclosing node as part of command -- avoid full document traversal;
 
wenzelm 
parents: 
44474 
diff
changeset
 | 
83  | 
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: 
39622 
diff
changeset
 | 
84  | 
|
| 
44607
 
274eff0ea12e
maintain name of *the* enclosing node as part of command -- avoid full document traversal;
 
wenzelm 
parents: 
44474 
diff
changeset
 | 
85  | 
def span(node_name: String, toks: List[Token]): Command =  | 
| 
 
274eff0ea12e
maintain name of *the* enclosing node as part of command -- avoid full document traversal;
 
wenzelm 
parents: 
44474 
diff
changeset
 | 
86  | 
new Command(Document.no_id, node_name, toks)  | 
| 44384 | 87  | 
|
88  | 
||
89  | 
/* perspective */  | 
|
90  | 
||
| 44474 | 91  | 
object Perspective  | 
92  | 
  {
 | 
|
93  | 
val empty: Perspective = Perspective(Nil)  | 
|
94  | 
}  | 
|
| 
44385
 
e7fdb008aa7d
propagate editor perspective through document model;
 
wenzelm 
parents: 
44384 
diff
changeset
 | 
95  | 
|
| 44474 | 96  | 
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
 | 
97  | 
  {
 | 
| 44474 | 98  | 
def same(that: Perspective): Boolean =  | 
99  | 
    {
 | 
|
100  | 
val cmds1 = this.commands  | 
|
101  | 
val cmds2 = that.commands  | 
|
102  | 
require(cmds1.forall(_.is_defined))  | 
|
103  | 
require(cmds2.forall(_.is_defined))  | 
|
104  | 
cmds1.length == cmds2.length &&  | 
|
105  | 
        (cmds1.iterator zip cmds2.iterator).forall({ case (c1, c2) => c1.id == c2.id })
 | 
|
106  | 
}  | 
|
| 
44385
 
e7fdb008aa7d
propagate editor perspective through document model;
 
wenzelm 
parents: 
44384 
diff
changeset
 | 
107  | 
}  | 
| 
34318
 
c13e168a8ae6
original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
 
wenzelm 
parents:  
diff
changeset
 | 
108  | 
}  | 
| 
 
c13e168a8ae6
original sources from Johannes Hölzl a48e0c6ab1aea77c52d596f7efc007a543d3d10c with minor modifications of directory layout;
 
wenzelm 
parents:  
diff
changeset
 | 
109  | 
|
| 38361 | 110  | 
|
| 34697 | 111  | 
class Command(  | 
| 
38150
 
67fc24df3721
simplified/refined document model: collection of named nodes, without proper dependencies yet;
 
wenzelm 
parents: 
37373 
diff
changeset
 | 
112  | 
val id: Document.Command_ID,  | 
| 
44607
 
274eff0ea12e
maintain name of *the* enclosing node as part of command -- avoid full document traversal;
 
wenzelm 
parents: 
44474 
diff
changeset
 | 
113  | 
val node_name: String,  | 
| 38373 | 114  | 
val span: List[Token])  | 
| 34451 | 115  | 
{
 | 
| 34859 | 116  | 
/* classification */  | 
| 
34500
 
384427c750c8
state_results: separate buffer for messages from running command;
 
wenzelm 
parents: 
34497 
diff
changeset
 | 
117  | 
|
| 
44385
 
e7fdb008aa7d
propagate editor perspective through document model;
 
wenzelm 
parents: 
44384 
diff
changeset
 | 
118  | 
def is_defined: Boolean = id != Document.no_id  | 
| 
 
e7fdb008aa7d
propagate editor perspective through document model;
 
wenzelm 
parents: 
44384 
diff
changeset
 | 
119  | 
|
| 36012 | 120  | 
def is_command: Boolean = !span.isEmpty && span.head.is_command  | 
| 34865 | 121  | 
def is_ignored: Boolean = span.forall(_.is_ignored)  | 
| 34859 | 122  | 
def is_malformed: Boolean = !is_command && !is_ignored  | 
123  | 
||
| 36012 | 124  | 
def name: String = if (is_command) span.head.content else ""  | 
| 37129 | 125  | 
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
 | 
126  | 
id + "/" + (if (is_command) name else if (is_ignored) "IGNORED" else "MALFORMED")  | 
| 34495 | 127  | 
|
| 34859 | 128  | 
|
129  | 
/* source text */  | 
|
| 34451 | 130  | 
|
| 34859 | 131  | 
val source: String = span.map(_.source).mkString  | 
| 38426 | 132  | 
def source(range: Text.Range): String = source.substring(range.start, range.stop)  | 
| 34859 | 133  | 
def length: Int = source.length  | 
| 
38572
 
0fe2c01ef7da
Command.State: accumulate markup reports uniformly;
 
wenzelm 
parents: 
38564 
diff
changeset
 | 
134  | 
|
| 38877 | 135  | 
val newlines =  | 
136  | 
    (0 /: Symbol.iterator(source)) {
 | 
|
137  | 
case (n, s) => if (Symbol.is_physical_newline(s)) n + 1 else n }  | 
|
138  | 
||
| 
38479
 
e628da370072
more efficient Markup_Tree, based on branches sorted by quasi-order;
 
wenzelm 
parents: 
38476 
diff
changeset
 | 
139  | 
val range: Text.Range = Text.Range(0, length)  | 
| 
34855
 
81d0410dc3ac
iterators for ranges of commands/starts -- avoid extra array per document;
 
wenzelm 
parents: 
34835 
diff
changeset
 | 
140  | 
|
| 34859 | 141  | 
lazy val symbol_index = new Symbol.Index(source)  | 
| 38579 | 142  | 
def decode(i: Text.Offset): Text.Offset = symbol_index.decode(i)  | 
143  | 
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
 | 
144  | 
|
| 
 
8b15d0f98962
explicit Document.State value, instead of individual state variables in Session, Command, Document;
 
wenzelm 
parents: 
38367 
diff
changeset
 | 
145  | 
|
| 
 
8b15d0f98962
explicit Document.State value, instead of individual state variables in Session, Command, Document;
 
wenzelm 
parents: 
38367 
diff
changeset
 | 
146  | 
/* accumulated results */  | 
| 
 
8b15d0f98962
explicit Document.State value, instead of individual state variables in Session, Command, Document;
 
wenzelm 
parents: 
38367 
diff
changeset
 | 
147  | 
|
| 38872 | 148  | 
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: 
34675 
diff
changeset
 | 
149  | 
}  |