8 |
8 |
9 |
9 |
10 import scala.collection.immutable.SortedMap |
10 import scala.collection.immutable.SortedMap |
11 |
11 |
12 |
12 |
13 object Debugger |
13 object Debugger { |
14 { |
|
15 /* thread context */ |
14 /* thread context */ |
16 |
15 |
17 case object Update |
16 case object Update |
18 |
17 |
19 sealed case class Debug_State(pos: Position.T, function: String) |
18 sealed case class Debug_State(pos: Position.T, function: String) |
20 type Threads = SortedMap[String, List[Debug_State]] |
19 type Threads = SortedMap[String, List[Debug_State]] |
21 |
20 |
22 sealed case class Context(thread_name: String, debug_states: List[Debug_State], index: Int = 0) |
21 sealed case class Context(thread_name: String, debug_states: List[Debug_State], index: Int = 0) { |
23 { |
|
24 def size: Int = debug_states.length + 1 |
22 def size: Int = debug_states.length + 1 |
25 def reset: Context = copy(index = 0) |
23 def reset: Context = copy(index = 0) |
26 def select(i: Int): Context = copy(index = i + 1) |
24 def select(i: Int): Context = copy(index = i + 1) |
27 |
25 |
28 def thread_state: Option[Debug_State] = debug_states.headOption |
26 def thread_state: Option[Debug_State] = debug_states.headOption |
54 active: Int = 0, // active views |
52 active: Int = 0, // active views |
55 break: Boolean = false, // break at next possible breakpoint |
53 break: Boolean = false, // break at next possible breakpoint |
56 active_breakpoints: Set[Long] = Set.empty, // explicit breakpoint state |
54 active_breakpoints: Set[Long] = Set.empty, // explicit breakpoint state |
57 threads: Threads = SortedMap.empty, // thread name ~> stack of debug states |
55 threads: Threads = SortedMap.empty, // thread name ~> stack of debug states |
58 focus: Map[String, Context] = Map.empty, // thread name ~> focus |
56 focus: Map[String, Context] = Map.empty, // thread name ~> focus |
59 output: Map[String, Command.Results] = Map.empty) // thread name ~> output messages |
57 output: Map[String, Command.Results] = Map.empty // thread name ~> output messages |
60 { |
58 ) { |
61 def set_break(b: Boolean): State = copy(break = b) |
59 def set_break(b: Boolean): State = copy(break = b) |
62 |
60 |
63 def is_active: Boolean = active > 0 |
61 def is_active: Boolean = active > 0 |
64 def inc_active: State = copy(active = active + 1) |
62 def inc_active: State = copy(active = active + 1) |
65 def dec_active: State = copy(active = active - 1) |
63 def dec_active: State = copy(active = active - 1) |
66 |
64 |
67 def toggle_breakpoint(breakpoint: Long): (Boolean, State) = |
65 def toggle_breakpoint(breakpoint: Long): (Boolean, State) = { |
68 { |
|
69 val active_breakpoints1 = |
66 val active_breakpoints1 = |
70 if (active_breakpoints(breakpoint)) active_breakpoints - breakpoint |
67 if (active_breakpoints(breakpoint)) active_breakpoints - breakpoint |
71 else active_breakpoints + breakpoint |
68 else active_breakpoints + breakpoint |
72 (active_breakpoints1(breakpoint), copy(active_breakpoints = active_breakpoints1)) |
69 (active_breakpoints1(breakpoint), copy(active_breakpoints = active_breakpoints1)) |
73 } |
70 } |
74 |
71 |
75 def get_thread(thread_name: String): List[Debug_State] = |
72 def get_thread(thread_name: String): List[Debug_State] = |
76 threads.getOrElse(thread_name, Nil) |
73 threads.getOrElse(thread_name, Nil) |
77 |
74 |
78 def update_thread(thread_name: String, debug_states: List[Debug_State]): State = |
75 def update_thread(thread_name: String, debug_states: List[Debug_State]): State = { |
79 { |
|
80 val threads1 = |
76 val threads1 = |
81 if (debug_states.nonEmpty) threads + (thread_name -> debug_states) |
77 if (debug_states.nonEmpty) threads + (thread_name -> debug_states) |
82 else threads - thread_name |
78 else threads - thread_name |
83 val focus1 = |
79 val focus1 = |
84 focus.get(thread_name) match { |
80 focus.get(thread_name) match { |
102 } |
98 } |
103 |
99 |
104 |
100 |
105 /* protocol handler */ |
101 /* protocol handler */ |
106 |
102 |
107 class Handler(session: Session) extends Session.Protocol_Handler |
103 class Handler(session: Session) extends Session.Protocol_Handler { |
108 { |
|
109 val debugger: Debugger = new Debugger(session) |
104 val debugger: Debugger = new Debugger(session) |
110 |
105 |
111 private def debugger_state(msg: Prover.Protocol_Output): Boolean = |
106 private def debugger_state(msg: Prover.Protocol_Output): Boolean = { |
112 { |
|
113 msg.properties match { |
107 msg.properties match { |
114 case Markup.Debugger_State(thread_name) => |
108 case Markup.Debugger_State(thread_name) => |
115 val msg_body = Symbol.decode_yxml_failsafe(msg.text) |
109 val msg_body = Symbol.decode_yxml_failsafe(msg.text) |
116 val debug_states = |
110 val debug_states = { |
117 { |
|
118 import XML.Decode._ |
111 import XML.Decode._ |
119 list(pair(properties, string))(msg_body).map({ |
112 list(pair(properties, string))(msg_body).map({ |
120 case (pos, function) => Debug_State(pos, function) |
113 case (pos, function) => Debug_State(pos, function) |
121 }) |
114 }) |
122 } |
115 } |
124 true |
117 true |
125 case _ => false |
118 case _ => false |
126 } |
119 } |
127 } |
120 } |
128 |
121 |
129 private def debugger_output(msg: Prover.Protocol_Output): Boolean = |
122 private def debugger_output(msg: Prover.Protocol_Output): Boolean = { |
130 { |
|
131 msg.properties match { |
123 msg.properties match { |
132 case Markup.Debugger_Output(thread_name) => |
124 case Markup.Debugger_Output(thread_name) => |
133 Symbol.decode_yxml_failsafe(msg.text) match { |
125 Symbol.decode_yxml_failsafe(msg.text) match { |
134 case List(XML.Elem(Markup(name, props @ Markup.Serial(i)), body)) => |
126 case List(XML.Elem(Markup(name, props @ Markup.Serial(i)), body)) => |
135 val message = XML.Elem(Markup(Markup.message(name), props), body) |
127 val message = XML.Elem(Markup(Markup.message(name), props), body) |
160 } |
151 } |
161 |
152 |
162 |
153 |
163 /* protocol commands */ |
154 /* protocol commands */ |
164 |
155 |
165 def update_thread(thread_name: String, debug_states: List[Debugger.Debug_State]): Unit = |
156 def update_thread(thread_name: String, debug_states: List[Debugger.Debug_State]): Unit = { |
166 { |
|
167 state.change(_.update_thread(thread_name, debug_states)) |
157 state.change(_.update_thread(thread_name, debug_states)) |
168 delay_update.invoke() |
158 delay_update.invoke() |
169 } |
159 } |
170 |
160 |
171 def add_output(thread_name: String, entry: Command.Results.Entry): Unit = |
161 def add_output(thread_name: String, entry: Command.Results.Entry): Unit = { |
172 { |
|
173 state.change(_.add_output(thread_name, entry)) |
162 state.change(_.add_output(thread_name, entry)) |
174 delay_update.invoke() |
163 delay_update.invoke() |
175 } |
164 } |
176 |
165 |
177 def is_active(): Boolean = session.is_ready && state.value.is_active |
166 def is_active(): Boolean = session.is_ready && state.value.is_active |
178 |
167 |
179 def ready(): Unit = |
168 def ready(): Unit = { |
180 { |
|
181 if (is_active()) |
169 if (is_active()) |
182 session.protocol_command("Debugger.init") |
170 session.protocol_command("Debugger.init") |
183 } |
171 } |
184 |
172 |
185 def init(): Unit = |
173 def init(): Unit = |
186 state.change(st => |
174 state.change(st => { |
187 { |
|
188 val st1 = st.inc_active |
175 val st1 = st.inc_active |
189 if (session.is_ready && !st.is_active && st1.is_active) |
176 if (session.is_ready && !st.is_active && st1.is_active) |
190 session.protocol_command("Debugger.init") |
177 session.protocol_command("Debugger.init") |
191 st1 |
178 st1 |
192 }) |
179 }) |
193 |
180 |
194 def exit(): Unit = |
181 def exit(): Unit = |
195 state.change(st => |
182 state.change(st => { |
196 { |
|
197 val st1 = st.dec_active |
183 val st1 = st.dec_active |
198 if (session.is_ready && st.is_active && !st1.is_active) |
184 if (session.is_ready && st.is_active && !st1.is_active) |
199 session.protocol_command("Debugger.exit") |
185 session.protocol_command("Debugger.exit") |
200 st1 |
186 st1 |
201 }) |
187 }) |
202 |
188 |
203 def is_break(): Boolean = state.value.break |
189 def is_break(): Boolean = state.value.break |
204 def set_break(b: Boolean): Unit = |
190 def set_break(b: Boolean): Unit = { |
205 { |
|
206 state.change(st => { |
191 state.change(st => { |
207 val st1 = st.set_break(b) |
192 val st1 = st.set_break(b) |
208 session.protocol_command("Debugger.break", b.toString) |
193 session.protocol_command("Debugger.break", b.toString) |
209 st1 |
194 st1 |
210 }) |
195 }) |
211 delay_update.invoke() |
196 delay_update.invoke() |
212 } |
197 } |
213 |
198 |
214 def active_breakpoint_state(breakpoint: Long): Option[Boolean] = |
199 def active_breakpoint_state(breakpoint: Long): Option[Boolean] = { |
215 { |
|
216 val st = state.value |
200 val st = state.value |
217 if (st.is_active) Some(st.active_breakpoints(breakpoint)) else None |
201 if (st.is_active) Some(st.active_breakpoints(breakpoint)) else None |
218 } |
202 } |
219 |
203 |
220 def breakpoint_state(breakpoint: Long): Boolean = |
204 def breakpoint_state(breakpoint: Long): Boolean = |
221 state.value.active_breakpoints(breakpoint) |
205 state.value.active_breakpoints(breakpoint) |
222 |
206 |
223 def toggle_breakpoint(command: Command, breakpoint: Long): Unit = |
207 def toggle_breakpoint(command: Command, breakpoint: Long): Unit = { |
224 { |
208 state.change(st => { |
225 state.change(st => |
209 val (breakpoint_state, st1) = st.toggle_breakpoint(breakpoint) |
226 { |
210 session.protocol_command( |
227 val (breakpoint_state, st1) = st.toggle_breakpoint(breakpoint) |
211 "Debugger.breakpoint", |
228 session.protocol_command( |
212 Symbol.encode(command.node_name.node), |
229 "Debugger.breakpoint", |
213 Document_ID(command.id), |
230 Symbol.encode(command.node_name.node), |
214 Value.Long(breakpoint), |
231 Document_ID(command.id), |
215 Value.Boolean(breakpoint_state)) |
232 Value.Long(breakpoint), |
216 st1 |
233 Value.Boolean(breakpoint_state)) |
217 }) |
234 st1 |
218 } |
235 }) |
219 |
236 } |
220 def status(focus: Option[Debugger.Context]): (Debugger.Threads, List[XML.Tree]) = { |
237 |
|
238 def status(focus: Option[Debugger.Context]): (Debugger.Threads, List[XML.Tree]) = |
|
239 { |
|
240 val st = state.value |
221 val st = state.value |
241 val output = |
222 val output = |
242 focus match { |
223 focus match { |
243 case None => Nil |
224 case None => Nil |
244 case Some(c) => |
225 case Some(c) => |
264 def continue(thread_name: String): Unit = input(thread_name, "continue") |
244 def continue(thread_name: String): Unit = input(thread_name, "continue") |
265 def step(thread_name: String): Unit = input(thread_name, "step") |
245 def step(thread_name: String): Unit = input(thread_name, "step") |
266 def step_over(thread_name: String): Unit = input(thread_name, "step_over") |
246 def step_over(thread_name: String): Unit = input(thread_name, "step_over") |
267 def step_out(thread_name: String): Unit = input(thread_name, "step_out") |
247 def step_out(thread_name: String): Unit = input(thread_name, "step_out") |
268 |
248 |
269 def clear_output(thread_name: String): Unit = |
249 def clear_output(thread_name: String): Unit = { |
270 { |
|
271 state.change(_.clear_output(thread_name)) |
250 state.change(_.clear_output(thread_name)) |
272 delay_update.invoke() |
251 delay_update.invoke() |
273 } |
252 } |
274 |
253 |
275 def eval(c: Debugger.Context, SML: Boolean, context: String, expression: String): Unit = |
254 def eval(c: Debugger.Context, SML: Boolean, context: String, expression: String): Unit = { |
276 { |
|
277 state.change(st => { |
255 state.change(st => { |
278 input(c.thread_name, "eval", c.debug_index.getOrElse(0).toString, |
256 input(c.thread_name, "eval", c.debug_index.getOrElse(0).toString, |
279 SML.toString, Symbol.encode(context), Symbol.encode(expression)) |
257 SML.toString, Symbol.encode(context), Symbol.encode(expression)) |
280 st.clear_output(c.thread_name) |
258 st.clear_output(c.thread_name) |
281 }) |
259 }) |
282 delay_update.invoke() |
260 delay_update.invoke() |
283 } |
261 } |
284 |
262 |
285 def print_vals(c: Debugger.Context, SML: Boolean, context: String): Unit = |
263 def print_vals(c: Debugger.Context, SML: Boolean, context: String): Unit = { |
286 { |
|
287 require(c.debug_index.isDefined) |
264 require(c.debug_index.isDefined) |
288 |
265 |
289 state.change(st => { |
266 state.change(st => { |
290 input(c.thread_name, "print_vals", c.debug_index.getOrElse(0).toString, |
267 input(c.thread_name, "print_vals", c.debug_index.getOrElse(0).toString, |
291 SML.toString, Symbol.encode(context)) |
268 SML.toString, Symbol.encode(context)) |