85 |
85 |
86 /** pipelined change parsing **/ |
86 /** pipelined change parsing **/ |
87 |
87 |
88 //{{{ |
88 //{{{ |
89 private case class Text_Edits( |
89 private case class Text_Edits( |
90 name: Document.Node.Name, |
|
91 previous: Future[Document.Version], |
90 previous: Future[Document.Version], |
92 text_edits: List[Document.Edit_Text], |
91 text_edits: List[Document.Edit_Text], |
93 version_result: Promise[Document.Version]) |
92 version_result: Promise[Document.Version]) |
94 |
93 |
95 private val (_, change_parser) = Simple_Thread.actor("change_parser", daemon = true) |
94 private val (_, change_parser) = Simple_Thread.actor("change_parser", daemon = true) |
97 var finished = false |
96 var finished = false |
98 while (!finished) { |
97 while (!finished) { |
99 receive { |
98 receive { |
100 case Stop => finished = true; reply(()) |
99 case Stop => finished = true; reply(()) |
101 |
100 |
102 case Text_Edits(name, previous, text_edits, version_result) => |
101 case Text_Edits(previous, text_edits, version_result) => |
103 val prev = previous.get_finished |
102 val prev = previous.get_finished |
104 val (doc_edits, version) = Thy_Syntax.text_edits(prover_syntax, prev, text_edits) |
103 val (doc_edits, version) = Thy_Syntax.text_edits(prover_syntax, prev, text_edits) |
105 version_result.fulfill(version) |
104 version_result.fulfill(version) |
106 sender ! Change_Node(name, doc_edits, prev, version) |
105 sender ! Change(doc_edits, prev, version) |
107 |
106 |
108 case bad => System.err.println("change_parser: ignoring bad message " + bad) |
107 case bad => System.err.println("change_parser: ignoring bad message " + bad) |
109 } |
108 } |
110 } |
109 } |
111 } |
110 } |
167 |
166 |
168 /* actor messages */ |
167 /* actor messages */ |
169 |
168 |
170 private case class Start(timeout: Time, args: List[String]) |
169 private case class Start(timeout: Time, args: List[String]) |
171 private case object Cancel_Execution |
170 private case object Cancel_Execution |
172 private case class Init_Node(name: Document.Node.Name, |
171 private case class Edit(edits: List[Document.Edit_Text]) |
173 header: Document.Node_Header, perspective: Text.Perspective, text: String) |
172 private case class Change( |
174 private case class Edit_Node(name: Document.Node.Name, |
|
175 header: Document.Node_Header, perspective: Text.Perspective, edits: List[Text.Edit]) |
|
176 private case class Change_Node( |
|
177 name: Document.Node.Name, |
|
178 doc_edits: List[Document.Edit_Command], |
173 doc_edits: List[Document.Edit_Command], |
179 previous: Document.Version, |
174 previous: Document.Version, |
180 version: Document.Version) |
175 version: Document.Version) |
181 private case class Messages(msgs: List[Isabelle_Process.Message]) |
176 private case class Messages(msgs: List[Isabelle_Process.Message]) |
182 |
177 |
265 } |
260 } |
266 } |
261 } |
267 } |
262 } |
268 |
263 |
269 |
264 |
270 /* incoming edits */ |
|
271 |
|
272 def handle_edits(name: Document.Node.Name, |
|
273 header: Document.Node_Header, edits: List[Document.Node.Edit[Text.Edit, Text.Perspective]]) |
|
274 //{{{ |
|
275 { |
|
276 val previous = global_state().history.tip.version |
|
277 |
|
278 prover.get.discontinue_execution() |
|
279 |
|
280 val text_edits = header_edit(name, header) :: edits.map(edit => (name, edit)) |
|
281 val version = Future.promise[Document.Version] |
|
282 val change = global_state >>> (_.continue_history(previous, text_edits, version)) |
|
283 |
|
284 change_parser ! Text_Edits(name, previous, text_edits, version) |
|
285 } |
|
286 //}}} |
|
287 |
|
288 |
|
289 /* exec state assignment */ |
|
290 |
|
291 def handle_assign(id: Document.Version_ID, assign: Document.Assign) |
|
292 { |
|
293 val cmds = global_state >>> (_.assign(id, assign)) |
|
294 delay_commands_changed.invoke(true, cmds) |
|
295 } |
|
296 |
|
297 |
|
298 /* removed versions */ |
|
299 |
|
300 def handle_removed(removed: List[Document.Version_ID]): Unit = |
|
301 global_state >> (_.removed_versions(removed)) |
|
302 |
|
303 |
|
304 /* resulting changes */ |
265 /* resulting changes */ |
305 |
266 |
306 def handle_change(change: Change_Node) |
267 def handle_change(change: Change) |
307 //{{{ |
268 //{{{ |
308 { |
269 { |
309 val previous = change.previous |
270 val previous = change.previous |
310 val version = change.version |
271 val version = change.version |
311 val name = change.name |
|
312 val doc_edits = change.doc_edits |
272 val doc_edits = change.doc_edits |
313 |
273 |
314 def id_command(command: Command) |
274 def id_command(command: Command) |
315 { |
275 { |
316 if (!global_state().defined_command(command.id)) { |
276 if (!global_state().defined_command(command.id)) { |
353 } |
313 } |
354 |
314 |
355 case Isabelle_Markup.Assign_Execs if output.is_protocol => |
315 case Isabelle_Markup.Assign_Execs if output.is_protocol => |
356 XML.content(output.body).mkString match { |
316 XML.content(output.body).mkString match { |
357 case Protocol.Assign(id, assign) => |
317 case Protocol.Assign(id, assign) => |
358 try { handle_assign(id, assign) } |
318 try { |
|
319 val cmds = global_state >>> (_.assign(id, assign)) |
|
320 delay_commands_changed.invoke(true, cmds) |
|
321 } |
359 catch { case _: Document.State.Fail => bad_output(output) } |
322 catch { case _: Document.State.Fail => bad_output(output) } |
360 case _ => bad_output(output) |
323 case _ => bad_output(output) |
361 } |
324 } |
362 // FIXME separate timeout event/message!? |
325 // FIXME separate timeout event/message!? |
363 if (prover.isDefined && System.currentTimeMillis() > prune_next) { |
326 if (prover.isDefined && System.currentTimeMillis() > prune_next) { |
367 } |
330 } |
368 |
331 |
369 case Isabelle_Markup.Removed_Versions if output.is_protocol => |
332 case Isabelle_Markup.Removed_Versions if output.is_protocol => |
370 XML.content(output.body).mkString match { |
333 XML.content(output.body).mkString match { |
371 case Protocol.Removed(removed) => |
334 case Protocol.Removed(removed) => |
372 try { handle_removed(removed) } |
335 try { |
|
336 global_state >> (_.removed_versions(removed)) |
|
337 } |
373 catch { case _: Document.State.Fail => bad_output(output) } |
338 catch { case _: Document.State.Fail => bad_output(output) } |
374 case _ => bad_output(output) |
339 case _ => bad_output(output) |
375 } |
340 } |
376 |
341 |
377 case Isabelle_Markup.Invoke_Scala(name, id) if output.is_protocol => |
342 case Isabelle_Markup.Invoke_Scala(name, id) if output.is_protocol => |
433 reply(()) |
398 reply(()) |
434 |
399 |
435 case Cancel_Execution if prover.isDefined => |
400 case Cancel_Execution if prover.isDefined => |
436 prover.get.cancel_execution() |
401 prover.get.cancel_execution() |
437 |
402 |
438 case Init_Node(name, header, perspective, text) if prover.isDefined => |
403 case Edit(edits) if prover.isDefined => |
439 // FIXME compare with existing node |
404 prover.get.discontinue_execution() |
440 handle_edits(name, header, |
405 |
441 List(Document.Node.Clear(), |
406 val previous = global_state().history.tip.version |
442 Document.Node.Edits(List(Text.Edit.insert(0, text))), |
407 val version = Future.promise[Document.Version] |
443 Document.Node.Perspective(perspective))) |
408 val change = global_state >>> (_.continue_history(previous, edits, version)) |
444 reply(()) |
409 change_parser ! Text_Edits(previous, edits, version) |
445 |
410 |
446 case Edit_Node(name, header, perspective, text_edits) if prover.isDefined => |
|
447 handle_edits(name, header, |
|
448 List(Document.Node.Edits(text_edits), Document.Node.Perspective(perspective))) |
|
449 reply(()) |
411 reply(()) |
450 |
412 |
451 case Messages(msgs) => |
413 case Messages(msgs) => |
452 msgs foreach { |
414 msgs foreach { |
453 case input: Isabelle_Process.Input => |
415 case input: Isabelle_Process.Input => |
458 if (output.is_syslog) syslog_messages.event(output) |
420 if (output.is_syslog) syslog_messages.event(output) |
459 if (output.is_stdout || output.is_stderr) raw_output_messages.event(output) |
421 if (output.is_stdout || output.is_stderr) raw_output_messages.event(output) |
460 all_messages.event(output) |
422 all_messages.event(output) |
461 } |
423 } |
462 |
424 |
463 case change: Change_Node |
425 case change: Change |
464 if prover.isDefined && global_state().is_assigned(change.previous) => |
426 if prover.isDefined && global_state().is_assigned(change.previous) => |
465 handle_change(change) |
427 handle_change(change) |
466 |
428 |
467 case bad if !bad.isInstanceOf[Change_Node] => |
429 case bad if !bad.isInstanceOf[Change] => |
468 System.err.println("session_actor: ignoring bad message " + bad) |
430 System.err.println("session_actor: ignoring bad message " + bad) |
469 } |
431 } |
470 } |
432 } |
471 //}}} |
433 //}}} |
472 } |
434 } |
481 |
443 |
482 def stop() { commands_changed_buffer !? Stop; change_parser !? Stop; session_actor !? Stop } |
444 def stop() { commands_changed_buffer !? Stop; change_parser !? Stop; session_actor !? Stop } |
483 |
445 |
484 def cancel_execution() { session_actor ! Cancel_Execution } |
446 def cancel_execution() { session_actor ! Cancel_Execution } |
485 |
447 |
|
448 def edit(edits: List[Document.Edit_Text]) |
|
449 { session_actor !? Edit(edits) } |
|
450 |
486 def init_node(name: Document.Node.Name, |
451 def init_node(name: Document.Node.Name, |
487 header: Document.Node_Header, perspective: Text.Perspective, text: String) |
452 header: Document.Node_Header, perspective: Text.Perspective, text: String) |
488 { session_actor !? Init_Node(name, header, perspective, text) } |
453 { |
|
454 edit(List(header_edit(name, header), |
|
455 name -> Document.Node.Clear(), // FIXME diff wrt. existing node |
|
456 name -> Document.Node.Edits(List(Text.Edit.insert(0, text))), |
|
457 name -> Document.Node.Perspective(perspective))) |
|
458 } |
489 |
459 |
490 def edit_node(name: Document.Node.Name, |
460 def edit_node(name: Document.Node.Name, |
491 header: Document.Node_Header, perspective: Text.Perspective, edits: List[Text.Edit]) |
461 header: Document.Node_Header, perspective: Text.Perspective, text_edits: List[Text.Edit]) |
492 { session_actor !? Edit_Node(name, header, perspective, edits) } |
462 { |
|
463 edit(List(header_edit(name, header), |
|
464 name -> Document.Node.Edits(text_edits), |
|
465 name -> Document.Node.Perspective(perspective))) |
|
466 } |
493 } |
467 } |