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 } |