src/Pure/System/session.scala
changeset 47629 645163d3b964
parent 47390 580c37559354
child 47653 4605d4341b8b
equal deleted inserted replaced
47628:3275758d274e 47629:645163d3b964
    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 }