src/Tools/jEdit/jedit_main/scala_console.scala
changeset 75444 331f96a67924
parent 75443 d6f2fbdc6322
child 75654 21164fd15e3d
equal deleted inserted replaced
75443:d6f2fbdc6322 75444:331f96a67924
    13 import console.{Console, ConsolePane, Shell, Output}
    13 import console.{Console, ConsolePane, Shell, Output}
    14 import org.gjt.sp.jedit.JARClassLoader
    14 import org.gjt.sp.jedit.JARClassLoader
    15 import java.io.{OutputStream, Writer, PrintWriter}
    15 import java.io.{OutputStream, Writer, PrintWriter}
    16 
    16 
    17 
    17 
       
    18 object Scala_Console {
       
    19   class Interpreter(context: Scala.Compiler.Context, val console: Console)
       
    20     extends Scala.Interpreter(context)
       
    21 
       
    22   def console_interpreter(console: Console): Option[Interpreter] =
       
    23     Scala.Interpreter.get { case int: Interpreter if int.console == console => int }
       
    24 
       
    25   def running_interpreter(): Interpreter = {
       
    26     val self = Thread.currentThread()
       
    27     Scala.Interpreter.get { case int: Interpreter if int.running_thread(self) => int }
       
    28       .getOrElse(error("Bad Scala interpreter thread"))
       
    29   }
       
    30 
       
    31   def running_console(): Console = running_interpreter().console
       
    32 
       
    33   val init = """
       
    34 import isabelle._
       
    35 import isabelle.jedit._
       
    36 val console = isabelle.jedit_main.Scala_Console.running_console()
       
    37 val view = console.getView()
       
    38 """
       
    39 }
       
    40 
    18 class Scala_Console extends Shell("Scala") {
    41 class Scala_Console extends Shell("Scala") {
    19   /* global state -- owned by GUI thread */
    42   /* global state -- owned by GUI thread */
    20 
       
    21   @volatile private var interpreters = Map.empty[Console, Interpreter]
       
    22 
    43 
    23   @volatile private var global_console: Console = null
    44   @volatile private var global_console: Console = null
    24   @volatile private var global_out: Output = null
    45   @volatile private var global_out: Output = null
    25   @volatile private var global_err: Output = null
    46   @volatile private var global_err: Output = null
    26 
    47 
    78     if (global_console == null || global_err == null) isabelle.Output.writeln(str)
    99     if (global_console == null || global_err == null) isabelle.Output.writeln(str)
    79     else GUI_Thread.later { global_err.print(global_console.getErrorColor, str) }
   100     else GUI_Thread.later { global_err.print(global_console.getErrorColor, str) }
    80   }
   101   }
    81 
   102 
    82 
   103 
    83   /* interpreter thread */
       
    84 
       
    85   private abstract class Request
       
    86   private case class Start(console: Console) extends Request
       
    87   private case class Execute(console: Console, out: Output, err: Output, command: String)
       
    88     extends Request
       
    89 
       
    90   private class Interpreter {
       
    91     private val running = Synchronized[Option[Thread]](None)
       
    92     def interrupt(): Unit = running.change({ opt => opt.foreach(_.interrupt()); opt })
       
    93 
       
    94     private val interp =
       
    95       Scala.Compiler.context(
       
    96           print_writer = new PrintWriter(console_writer, true),
       
    97           error = report_error,
       
    98           jar_dirs = JEdit_Lib.directories,
       
    99           class_loader = Some(new JARClassLoader)).interp
       
   100 
       
   101     val thread: Consumer_Thread[Request] = Consumer_Thread.fork("Scala_Console") {
       
   102       case Start(console) =>
       
   103         interp.bind("view", "org.gjt.sp.jedit.View", console.getView)
       
   104         interp.bind("console", "console.Console", console)
       
   105         interp.interpret("import isabelle._; import isabelle.jedit._")
       
   106         true
       
   107 
       
   108       case Execute(console, out, err, command) =>
       
   109         with_console(console, out, err) {
       
   110           try {
       
   111             running.change(_ => Some(Thread.currentThread()))
       
   112             interp.interpret(command)
       
   113           }
       
   114           finally {
       
   115             running.change(_ => None)
       
   116             Exn.Interrupt.dispose()
       
   117           }
       
   118           GUI_Thread.later {
       
   119             if (err != null) err.commandDone()
       
   120             out.commandDone()
       
   121           }
       
   122           true
       
   123         }
       
   124     }
       
   125   }
       
   126 
       
   127 
       
   128   /* jEdit console methods */
   104   /* jEdit console methods */
   129 
   105 
   130   override def openConsole(console: Console): Unit = {
   106   override def openConsole(console: Console): Unit = {
   131     val interp = new Interpreter
   107     val context =
   132     interp.thread.send(Start(console))
   108       Scala.Compiler.context(
   133     interpreters += (console -> interp)
   109       print_writer = new PrintWriter(console_writer, true),
       
   110       error = report_error,
       
   111       jar_dirs = JEdit_Lib.directories,
       
   112       class_loader = Some(new JARClassLoader))
       
   113 
       
   114     val interpreter = new Scala_Console.Interpreter(context, console)
       
   115     interpreter.execute(_.interp.interpret(Scala_Console.init))
   134   }
   116   }
   135 
   117 
   136   override def closeConsole(console: Console): Unit = {
   118   override def closeConsole(console: Console): Unit =
   137     interpreters.get(console) match {
   119     Scala_Console.console_interpreter(console).foreach(_.shutdown())
   138       case Some(interp) =>
       
   139         interp.interrupt()
       
   140         interp.thread.shutdown()
       
   141         interpreters -= console
       
   142       case None =>
       
   143     }
       
   144   }
       
   145 
   120 
   146   override def printInfoMessage(out: Output): Unit = {
   121   override def printInfoMessage(out: Output): Unit = {
   147     out.print(null,
   122     out.print(null,
   148      "This shell evaluates Isabelle/Scala expressions.\n\n" +
   123      "This shell evaluates Isabelle/Scala expressions.\n\n" +
   149      "The contents of package isabelle and isabelle.jedit are imported.\n" +
   124      "The contents of package isabelle and isabelle.jedit are imported.\n" +
   160 
   135 
   161   override def execute(
   136   override def execute(
   162     console: Console,
   137     console: Console,
   163     input: String,
   138     input: String,
   164     out: Output,
   139     out: Output,
   165     err: Output, command: String
   140     err: Output,
       
   141     command: String
   166   ): Unit = {
   142   ): Unit = {
   167     interpreters(console).thread.send(Execute(console, out, err, command))
   143     Scala_Console.console_interpreter(console).foreach(interpreter =>
       
   144       interpreter.execute { context =>
       
   145         with_console(console, out, err) { context.interp.interpret(command) }
       
   146         GUI_Thread.later {
       
   147           Option(err).foreach(_.commandDone())
       
   148           out.commandDone()
       
   149         }
       
   150       })
   168   }
   151   }
   169 
   152 
   170   override def stop(console: Console): Unit =
   153   override def stop(console: Console): Unit =
   171     interpreters.get(console).foreach(_.interrupt())
   154     Scala_Console.console_interpreter(console).foreach(_.shutdown())
   172 }
   155 }