src/Tools/jEdit/src/proofdocument/session.scala
changeset 34820 a8ba6cde13e9
parent 34819 86cb7f8e5a0d
child 34823 2f3ea37c5958
--- a/src/Tools/jEdit/src/proofdocument/session.scala	Wed Dec 30 21:57:29 2009 +0100
+++ b/src/Tools/jEdit/src/proofdocument/session.scala	Thu Dec 31 00:38:15 2009 +0100
@@ -7,6 +7,7 @@
 package isabelle.proofdocument
 
 
+import scala.actors.TIMEOUT
 import scala.actors.Actor._
 
 
@@ -64,14 +65,13 @@
   /** main actor **/
 
   private case class Register(entity: Session.Entity)
-  private case class Start(args: List[String])
+  private case class Start(timeout: Int, args: List[String])
   private case object Stop
   private case class Begin_Document(path: String)
 
   private val session_actor = actor {
 
     var prover: Isabelle_Process with Isar_Document = null
-    var prover_ready = false
 
     def register(entity: Session.Entity) { entities += (entity.id -> entity) }
 
@@ -124,10 +124,7 @@
             case XML.Elem(Markup.KEYWORD_DECL, (Markup.NAME, name) :: _, _) =>
               syntax += name
 
-            // process ready (after initialization)
-            case XML.Elem(Markup.READY, _, _) => prover_ready = true
-
-          case _ =>
+            case _ =>
           }
         }
       }
@@ -135,29 +132,73 @@
         prover = null
     }
 
-    val xml_cache = new XML.Cache(131071)
+
+    /* prover startup */
+
+    def startup_error(): String =
+    {
+      val buf = new StringBuilder
+      while (
+        receiveWithin(0) {
+          case result: Isabelle_Process.Result =>
+            if (result.is_raw) {
+              for (text <- XML.content(result.message))
+                buf.append(text)
+            }
+            true
+          case TIMEOUT => false
+        }) {}
+      buf.toString
+    }
+
+    def prover_startup(timeout: Int): Option[String] =
+    {
+      receiveWithin(timeout) {
+        case result: Isabelle_Process.Result
+          if result.kind == Isabelle_Process.Kind.INIT =>
+          while (receive {
+            case result: Isabelle_Process.Result =>
+              handle_result(result); !result.is_ready
+            }) {}
+          None
+
+        case result: Isabelle_Process.Result
+          if result.kind == Isabelle_Process.Kind.EXIT =>
+          Some(startup_error())
+
+        case TIMEOUT =>  // FIXME clarify
+          prover.kill; Some(startup_error())
+      }
+    }
 
 
     /* main loop */
 
+    val xml_cache = new XML.Cache(131071)
+
     loop {
       react {
         case Register(entity: Session.Entity) =>
           register(entity)
           reply(())
 
-        case Start(args) =>
+        case Start(timeout, args) =>
           if (prover == null) {
             prover = new Isabelle_Process(system, self, args:_*) with Isar_Document
-            reply(())
+            val origin = sender
+            val opt_err = prover_startup(timeout)
+            if (opt_err.isDefined) prover = null
+            origin ! opt_err
+          }
+          else reply(None)
+
+        case Stop =>  // FIXME clarify; synchronous
+          if (prover != null) {
+            prover.kill
+            prover = null
           }
 
-        case Stop =>  // FIXME clarify
-          if (prover != null)
-            prover.kill
-          prover_ready = false
-
-        case Begin_Document(path: String) if prover_ready =>
+        case Begin_Document(path: String) if prover != null =>
           val id = create_id()
           val doc = Proof_Document.empty(id)
           register(doc)
@@ -165,13 +206,13 @@
           prover.begin_document(id, path)
           reply(doc)
 
-        case change: Change if prover_ready =>
+        case change: Change if prover != null =>
           handle_change(change)
 
         case result: Isabelle_Process.Result =>
           handle_result(result.cache(xml_cache))
 
-        case bad if prover_ready =>
+        case bad if prover != null =>
           System.err.println("session_actor: ignoring bad message " + bad)
       }
     }
@@ -182,7 +223,9 @@
 
   def register_entity(entity: Session.Entity) { session_actor !? Register(entity) }
 
-  def start(args: List[String]) { session_actor !? Start(args) }
+  def start(timeout: Int, args: List[String]): Option[String] =
+    (session_actor !? Start(timeout, args)).asInstanceOf[Option[String]]
+
   def stop() { session_actor ! Stop }
   def input(change: Change) { session_actor ! change }