60749
|
1 |
/* Title: Pure/Tools/debugger.scala
|
|
2 |
Author: Makarius
|
|
3 |
|
|
4 |
Interactive debugger for Isabelle/ML.
|
|
5 |
*/
|
|
6 |
|
|
7 |
package isabelle
|
|
8 |
|
|
9 |
|
|
10 |
object Debugger
|
|
11 |
{
|
60834
|
12 |
/* global state */
|
|
13 |
|
60835
|
14 |
sealed case class State(
|
|
15 |
session: Session = new Session(Resources.empty),
|
60834
|
16 |
output: Map[String, Command.Results] = Map.empty) // thread name ~> output messages
|
|
17 |
{
|
|
18 |
def add_output(name: String, entry: Command.Results.Entry): State =
|
|
19 |
copy(output = output + (name -> (output.getOrElse(name, Command.Results.empty) + entry)))
|
|
20 |
}
|
|
21 |
|
|
22 |
private val global_state = Synchronized(State())
|
|
23 |
def current_state(): State = global_state.value
|
|
24 |
|
|
25 |
|
60835
|
26 |
/* protocol handler */
|
60749
|
27 |
|
60835
|
28 |
sealed case class Update(thread_names: Set[String])
|
60749
|
29 |
|
|
30 |
class Handler extends Session.Protocol_Handler
|
|
31 |
{
|
60835
|
32 |
private var updated = Set.empty[String]
|
|
33 |
private val delay_update =
|
|
34 |
Simple_Thread.delay_first(current_state().session.output_delay) {
|
|
35 |
current_state().session.debugger_updates.post(Update(updated))
|
|
36 |
updated = Set.empty
|
|
37 |
}
|
|
38 |
private def update(name: String)
|
|
39 |
{
|
|
40 |
updated += name
|
|
41 |
delay_update.invoke()
|
|
42 |
}
|
|
43 |
|
60830
|
44 |
private def debugger_output(prover: Prover, msg: Prover.Protocol_Output): Boolean =
|
|
45 |
{
|
|
46 |
msg.properties match {
|
60835
|
47 |
case Markup.Debugger_Output(thread_name) =>
|
60834
|
48 |
val msg_body =
|
|
49 |
prover.xml_cache.body(
|
|
50 |
YXML.parse_body_failsafe(UTF8.decode_permissive(msg.bytes)))
|
|
51 |
msg_body match {
|
|
52 |
case List(XML.Elem(Markup(name, props @ Markup.Serial(i)), body)) =>
|
|
53 |
val message = XML.Elem(Markup(Markup.message(name), props), body)
|
60835
|
54 |
global_state.change(_.add_output(thread_name, i -> message))
|
|
55 |
update(thread_name)
|
60834
|
56 |
true
|
|
57 |
case _ => false
|
|
58 |
}
|
60830
|
59 |
case _ => false
|
|
60 |
}
|
|
61 |
}
|
|
62 |
|
|
63 |
val functions =
|
|
64 |
Map(Markup.DEBUGGER_OUTPUT -> debugger_output _)
|
60749
|
65 |
}
|
60765
|
66 |
|
|
67 |
|
|
68 |
/* protocol commands */
|
|
69 |
|
60835
|
70 |
def init(new_session: Session)
|
|
71 |
{
|
|
72 |
global_state.change(_.copy(session = new_session))
|
|
73 |
current_state().session.protocol_command("Debugger.init")
|
|
74 |
}
|
60765
|
75 |
|
60835
|
76 |
def cancel(name: String): Unit =
|
|
77 |
current_state().session.protocol_command("Debugger.cancel", name)
|
60765
|
78 |
|
60835
|
79 |
def input(name: String, msg: String*): Unit =
|
|
80 |
current_state().session.protocol_command("Debugger.input", (name :: msg.toList):_*)
|
60749
|
81 |
}
|