| author | wenzelm | 
| Sun, 03 Sep 2023 16:18:06 +0200 | |
| changeset 78637 | 9a5d86549719 | 
| parent 77028 | f5896dea6fce | 
| child 78605 | 0bbbf8e26708 | 
| permissions | -rw-r--r-- | 
| 71849 | 1 | /* Title: Pure/System/scala.scala | 
| 43744 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 2 | Author: Makarius | 
| 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 3 | |
| 71849 | 4 | Support for Scala at runtime. | 
| 43744 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 5 | */ | 
| 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 6 | |
| 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 7 | package isabelle | 
| 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 8 | |
| 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 9 | |
| 75654 | 10 | import java.io.{File => JFile, PrintStream, ByteArrayOutputStream, OutputStream}
 | 
| 11 | ||
| 12 | import scala.collection.mutable | |
| 13 | import scala.annotation.tailrec | |
| 56730 
e723f041b6d0
tuned signature -- separate pool for JFuture tasks, which can be canceled;
 wenzelm parents: 
56667diff
changeset | 14 | |
| 75654 | 15 | import dotty.tools.dotc.CompilationUnit | 
| 16 | import dotty.tools.dotc.ast.Trees.PackageDef | |
| 17 | import dotty.tools.dotc.ast.untpd | |
| 18 | import dotty.tools.dotc.core.Contexts.{Context => CompilerContext}
 | |
| 19 | import dotty.tools.dotc.core.NameOps.moduleClassName | |
| 20 | import dotty.tools.dotc.core.{Phases, StdNames}
 | |
| 21 | import dotty.tools.dotc.interfaces | |
| 22 | import dotty.tools.dotc.reporting.{Diagnostic, ConsoleReporter}
 | |
| 23 | import dotty.tools.dotc.util.{SourceFile, SourcePosition, NoSourcePosition}
 | |
| 24 | import dotty.tools.repl | |
| 25 | import dotty.tools.repl.{ReplCompiler, ReplDriver}
 | |
| 26 | ||
| 43744 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 27 | |
| 75393 | 28 | object Scala {
 | 
| 72193 | 29 | /** registered functions **/ | 
| 30 | ||
| 75393 | 31 |   abstract class Fun(val name: String, val thread: Boolean = false) {
 | 
| 72193 | 32 | override def toString: String = name | 
| 75586 | 33 | def single: Boolean = false | 
| 34 | def bytes: Boolean = false | |
| 72756 | 35 | def position: Properties.T = here.position | 
| 36 | def here: Scala_Project.Here | |
| 77027 | 37 | def invoke(session: Session, args: List[Bytes]): List[Bytes] | 
| 73565 | 38 | } | 
| 39 | ||
| 75588 | 40 |   trait Single_Fun extends Fun { override def single: Boolean = true }
 | 
| 41 |   trait Bytes_Fun extends Fun { override def bytes: Boolean = true }
 | |
| 75586 | 42 | |
| 73565 | 43 | abstract class Fun_Strings(name: String, thread: Boolean = false) | 
| 75393 | 44 |   extends Fun(name, thread = thread) {
 | 
| 77027 | 45 | override def invoke(session: Session, args: List[Bytes]): List[Bytes] = | 
| 73565 | 46 | apply(args.map(_.text)).map(Bytes.apply) | 
| 47 | def apply(args: List[String]): List[String] | |
| 48 | } | |
| 49 | ||
| 50 | abstract class Fun_String(name: String, thread: Boolean = false) | |
| 75588 | 51 |   extends Fun_Strings(name, thread = thread) with Single_Fun {
 | 
| 73565 | 52 | override def apply(args: List[String]): List[String] = | 
| 73571 | 53 | List(apply(Library.the_single(args))) | 
| 72193 | 54 | def apply(arg: String): String | 
| 55 | } | |
| 56 | ||
| 75588 | 57 | abstract class Fun_Bytes(name: String, thread: Boolean = false) | 
| 58 |     extends Fun(name, thread = thread) with Single_Fun with Bytes_Fun {
 | |
| 77027 | 59 | override def invoke(session: Session, args: List[Bytes]): List[Bytes] = | 
| 75588 | 60 | List(apply(Library.the_single(args))) | 
| 61 | def apply(arg: Bytes): Bytes | |
| 62 | } | |
| 63 | ||
| 75586 | 64 |   val encode_fun: XML.Encode.T[Fun] = { fun =>
 | 
| 65 | import XML.Encode._ | |
| 66 | pair(string, pair(pair(bool, bool), properties))( | |
| 67 | fun.name, ((fun.single, fun.bytes), fun.position)) | |
| 68 | } | |
| 69 | ||
| 72193 | 70 | class Functions(val functions: Fun*) extends Isabelle_System.Service | 
| 71 | ||
| 72 | lazy val functions: List[Fun] = | |
| 73 | Isabelle_System.make_services(classOf[Functions]).flatMap(_.functions) | |
| 74 | ||
| 75 | ||
| 76 | ||
| 72152 | 77 | /** demo functions **/ | 
| 78 | ||
| 75393 | 79 |   object Echo extends Fun_String("echo") {
 | 
| 72756 | 80 | val here = Scala_Project.here | 
| 72193 | 81 | def apply(arg: String): String = arg | 
| 82 | } | |
| 72152 | 83 | |
| 75393 | 84 |   object Sleep extends Fun_String("sleep") {
 | 
| 72756 | 85 | val here = Scala_Project.here | 
| 75393 | 86 |     def apply(seconds: String): String = {
 | 
| 72193 | 87 | val t = | 
| 88 |         seconds match {
 | |
| 89 | case Value.Double(s) => Time.seconds(s) | |
| 90 |           case _ => error("Malformed argument: " + quote(seconds))
 | |
| 91 | } | |
| 92 | val t0 = Time.now() | |
| 73702 
7202e12cb324
tuned signature --- following hints by IntelliJ IDEA;
 wenzelm parents: 
73576diff
changeset | 93 | t.sleep() | 
| 72193 | 94 | val t1 = Time.now() | 
| 95 | (t1 - t0).toString | |
| 96 | } | |
| 72152 | 97 | } | 
| 98 | ||
| 99 | ||
| 100 | ||
| 71870 | 101 | /** compiler **/ | 
| 71850 | 102 | |
| 75393 | 103 |   object Compiler {
 | 
| 75654 | 104 |     object Message {
 | 
| 105 |       object Kind extends Enumeration {
 | |
| 106 | val error, warning, info, other = Value | |
| 107 | } | |
| 108 | private val Header = """^--.* (Error|Warning|Info): .*$""".r | |
| 109 | val header_kind: String => Kind.Value = | |
| 110 |         {
 | |
| 111 | case "Error" => Kind.error | |
| 112 | case "Warning" => Kind.warning | |
| 113 | case "Info" => Kind.info | |
| 114 | case _ => Kind.other | |
| 115 | } | |
| 116 | ||
| 117 | // see compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala | |
| 118 |       def split(str: String): List[Message] = {
 | |
| 119 | var kind = Kind.other | |
| 120 | val text = new mutable.StringBuilder | |
| 121 | val result = new mutable.ListBuffer[Message] | |
| 122 | ||
| 123 |         def flush(): Unit = {
 | |
| 124 |           if (text.nonEmpty) { result += Message(kind, text.toString) }
 | |
| 125 | kind = Kind.other | |
| 126 | text.clear() | |
| 127 | } | |
| 128 | ||
| 129 |         for (line <- Library.trim_split_lines(str)) {
 | |
| 130 |           line match {
 | |
| 131 | case Header(k) => flush(); kind = header_kind(k) | |
| 132 |             case _ => if (line.startsWith("-- ")) flush()
 | |
| 133 | } | |
| 134 |           if (text.nonEmpty) { text += '\n' }
 | |
| 135 | text ++= line | |
| 136 | } | |
| 137 | flush() | |
| 138 | result.toList | |
| 139 | } | |
| 140 | } | |
| 141 | ||
| 142 | sealed case class Message(kind: Message.Kind.Value, text: String) | |
| 143 |     {
 | |
| 144 | def is_error: Boolean = kind == Message.Kind.error | |
| 145 | override def toString: String = text | |
| 146 | } | |
| 147 | ||
| 148 | sealed case class Result( | |
| 149 | state: repl.State, | |
| 150 | messages: List[Message], | |
| 151 | unit: Option[CompilationUnit] = None | |
| 152 |     ) {
 | |
| 153 | val errors: List[String] = messages.flatMap(msg => if (msg.is_error) Some(msg.text) else None) | |
| 154 | def ok: Boolean = errors.isEmpty | |
| 155 | def check_state: repl.State = if (ok) state else error(cat_lines(errors)) | |
| 156 | override def toString: String = if (ok) "Result(ok)" else "Result(error)" | |
| 157 | } | |
| 75443 | 158 | |
| 71868 | 159 | def context( | 
| 75654 | 160 | settings: List[String] = Nil, | 
| 75702 | 161 | jar_files: List[JFile] = Nil, | 
| 75442 | 162 | class_loader: Option[ClassLoader] = None | 
| 75393 | 163 |     ): Context = {
 | 
| 75654 | 164 | val isabelle_settings = | 
| 165 |         Word.explode(Isabelle_System.getenv_strict("ISABELLE_SCALAC_OPTIONS"))
 | |
| 75705 | 166 | val classpath = Classpath(jar_files = jar_files) | 
| 167 | new Context(isabelle_settings ::: settings, classpath, class_loader) | |
| 71864 | 168 | } | 
| 71850 | 169 | |
| 75442 | 170 | class Context private [Compiler]( | 
| 75705 | 171 | _settings: List[String], | 
| 172 | val classpath: Classpath, | |
| 75654 | 173 | val class_loader: Option[ClassLoader] = None | 
| 75442 | 174 |     ) {
 | 
| 75705 | 175 | def settings: List[String] = | 
| 176 |         _settings ::: List("-classpath", classpath.platform_path)
 | |
| 177 | ||
| 75654 | 178 | private val out_stream = new ByteArrayOutputStream(1024) | 
| 179 | private val out = new PrintStream(out_stream) | |
| 180 | private val driver: ReplDriver = new ReplDriver(settings.toArray, out, class_loader) | |
| 71869 | 181 | |
| 75654 | 182 | def init_state: repl.State = driver.initialState | 
| 71850 | 183 | |
| 75654 | 184 |       def compile(source: String, state: repl.State = init_state): Result = {
 | 
| 185 | out.flush() | |
| 186 | out_stream.reset() | |
| 76537 | 187 | given repl.State = state | 
| 188 | val state1 = driver.run(source) | |
| 75654 | 189 | out.flush() | 
| 190 | val messages = Message.split(out_stream.toString(UTF8.charset)) | |
| 191 | out_stream.reset() | |
| 192 | Result(state1, messages) | |
| 193 | } | |
| 71864 | 194 | } | 
| 72194 | 195 | } | 
| 71850 | 196 | |
| 75393 | 197 |   object Toplevel extends Fun_String("scala_toplevel") {
 | 
| 72756 | 198 | val here = Scala_Project.here | 
| 75654 | 199 |     def apply(source: String): String = {
 | 
| 72194 | 200 | val errors = | 
| 75654 | 201 |         try { Compiler.context().compile(source).errors.map("Scala error: " + _) }
 | 
| 72194 | 202 |         catch { case ERROR(msg) => List(msg) }
 | 
| 203 |       locally { import XML.Encode._; YXML.string_of_body(list(string)(errors)) }
 | |
| 72193 | 204 | } | 
| 71872 | 205 | } | 
| 206 | ||
| 71850 | 207 | |
| 208 | ||
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 209 | /** interpreter thread **/ | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 210 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 211 |   object Interpreter {
 | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 212 | /* requests */ | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 213 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 214 | sealed abstract class Request | 
| 75654 | 215 | case class Execute(command: (Compiler.Context, repl.State) => repl.State) extends Request | 
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 216 | case object Shutdown extends Request | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 217 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 218 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 219 | /* known interpreters */ | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 220 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 221 | private val known = Synchronized(Set.empty[Interpreter]) | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 222 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 223 | def add(interpreter: Interpreter): Unit = known.change(_ + interpreter) | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 224 | def del(interpreter: Interpreter): Unit = known.change(_ - interpreter) | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 225 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 226 | def get[A](which: PartialFunction[Interpreter, A]): Option[A] = | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 227 | known.value.collectFirst(which) | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 228 | } | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 229 | |
| 75654 | 230 |   class Interpreter(context: Compiler.Context, out: OutputStream = Console.out) {
 | 
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 231 | interpreter => | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 232 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 233 | private val running = Synchronized[Option[Thread]](None) | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 234 | def running_thread(thread: Thread): Boolean = running.value.contains(thread) | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 235 |     def interrupt_thread(): Unit = running.change({ opt => opt.foreach(_.interrupt()); opt })
 | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 236 | |
| 75654 | 237 | private var state = context.init_state | 
| 238 | ||
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 239 | private lazy val thread: Consumer_Thread[Interpreter.Request] = | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 240 |       Consumer_Thread.fork("Scala.Interpreter") {
 | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 241 | case Interpreter.Execute(command) => | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 242 |           try {
 | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 243 | running.change(_ => Some(Thread.currentThread())) | 
| 75654 | 244 | state = command(context, state) | 
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 245 | } | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 246 |           finally {
 | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 247 | running.change(_ => None) | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 248 | Exn.Interrupt.dispose() | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 249 | } | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 250 | true | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 251 | case Interpreter.Shutdown => | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 252 | Interpreter.del(interpreter) | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 253 | false | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 254 | } | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 255 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 256 |     def shutdown(): Unit = {
 | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 257 | thread.send(Interpreter.Shutdown) | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 258 | interrupt_thread() | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 259 | thread.shutdown() | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 260 | } | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 261 | |
| 75654 | 262 | def execute(command: (Compiler.Context, repl.State) => repl.State): Unit = | 
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 263 | thread.send(Interpreter.Execute(command)) | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 264 | |
| 75654 | 265 | def reset(): Unit = | 
| 266 | thread.send(Interpreter.Execute((context, _) => context.init_state)) | |
| 267 | ||
| 75444 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 268 | Interpreter.add(interpreter) | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 269 | thread | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 270 | } | 
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 271 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 272 | |
| 
331f96a67924
clarified management of interpreter threads: more generic;
 wenzelm parents: 
75443diff
changeset | 273 | |
| 71871 
28def00726ca
more robust isabelle.Functions --- avoid Java reflection with unclear class/object treatment;
 wenzelm parents: 
71870diff
changeset | 274 | /** invoke Scala functions from ML **/ | 
| 
28def00726ca
more robust isabelle.Functions --- avoid Java reflection with unclear class/object treatment;
 wenzelm parents: 
71870diff
changeset | 275 | |
| 
28def00726ca
more robust isabelle.Functions --- avoid Java reflection with unclear class/object treatment;
 wenzelm parents: 
71870diff
changeset | 276 | /* invoke function */ | 
| 43748 | 277 | |
| 75393 | 278 |   object Tag extends Enumeration {
 | 
| 65638 | 279 | val NULL, OK, ERROR, FAIL, INTERRUPT = Value | 
| 43748 | 280 | } | 
| 43744 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 281 | |
| 73419 
22f3f2117ed7
clarified signature: function_thread is determined in Isabelle/Scala, not Isabelle/ML;
 wenzelm parents: 
73418diff
changeset | 282 | def function_thread(name: String): Boolean = | 
| 
22f3f2117ed7
clarified signature: function_thread is determined in Isabelle/Scala, not Isabelle/ML;
 wenzelm parents: 
73418diff
changeset | 283 |     functions.find(fun => fun.name == name) match {
 | 
| 
22f3f2117ed7
clarified signature: function_thread is determined in Isabelle/Scala, not Isabelle/ML;
 wenzelm parents: 
73418diff
changeset | 284 | case Some(fun) => fun.thread | 
| 
22f3f2117ed7
clarified signature: function_thread is determined in Isabelle/Scala, not Isabelle/ML;
 wenzelm parents: 
73418diff
changeset | 285 | case None => false | 
| 
22f3f2117ed7
clarified signature: function_thread is determined in Isabelle/Scala, not Isabelle/ML;
 wenzelm parents: 
73418diff
changeset | 286 | } | 
| 
22f3f2117ed7
clarified signature: function_thread is determined in Isabelle/Scala, not Isabelle/ML;
 wenzelm parents: 
73418diff
changeset | 287 | |
| 77027 | 288 | def function_body(session: Session, name: String, args: List[Bytes]): (Tag.Value, List[Bytes]) = | 
| 71873 | 289 |     functions.find(fun => fun.name == name) match {
 | 
| 290 | case Some(fun) => | |
| 77027 | 291 |         Exn.capture { fun.invoke(session, args) } match {
 | 
| 73565 | 292 | case Exn.Res(null) => (Tag.NULL, Nil) | 
| 43748 | 293 | case Exn.Res(res) => (Tag.OK, res) | 
| 73565 | 294 | case Exn.Exn(Exn.Interrupt()) => (Tag.INTERRUPT, Nil) | 
| 295 | case Exn.Exn(e) => (Tag.ERROR, List(Bytes(Exn.message(e)))) | |
| 43748 | 296 | } | 
| 73565 | 297 |       case None => (Tag.FAIL, List(Bytes("Unknown Isabelle/Scala function: " + quote(name))))
 | 
| 43748 | 298 | } | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 299 | |
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 300 | |
| 72157 | 301 | /* protocol handler */ | 
| 302 | ||
| 75393 | 303 |   class Handler extends Session.Protocol_Handler {
 | 
| 72157 | 304 | private var session: Session = null | 
| 305 | private var futures = Map.empty[String, Future[Unit]] | |
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 306 | |
| 72213 | 307 | override def init(session: Session): Unit = | 
| 308 |       synchronized { this.session = session }
 | |
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 309 | |
| 75380 | 310 |     override def exit(): Unit = synchronized {
 | 
| 72157 | 311 | for ((id, future) <- futures) cancel(id, future) | 
| 312 | futures = Map.empty | |
| 313 | } | |
| 65219 | 314 | |
| 73565 | 315 | private def result(id: String, tag: Scala.Tag.Value, res: List[Bytes]): Unit = | 
| 75380 | 316 |       synchronized {
 | 
| 72157 | 317 |         if (futures.isDefinedAt(id)) {
 | 
| 73565 | 318 |           session.protocol_command_raw("Scala.result", Bytes(id) :: Bytes(tag.id.toString) :: res)
 | 
| 72157 | 319 | futures -= id | 
| 320 | } | |
| 321 | } | |
| 65220 | 322 | |
| 75393 | 323 |     private def cancel(id: String, future: Future[Unit]): Unit = {
 | 
| 73367 | 324 | future.cancel() | 
| 73565 | 325 | result(id, Scala.Tag.INTERRUPT, Nil) | 
| 72157 | 326 | } | 
| 327 | ||
| 75380 | 328 |     private def invoke_scala(msg: Prover.Protocol_Output): Boolean = synchronized {
 | 
| 72157 | 329 |       msg.properties match {
 | 
| 73419 
22f3f2117ed7
clarified signature: function_thread is determined in Isabelle/Scala, not Isabelle/ML;
 wenzelm parents: 
73418diff
changeset | 330 | case Markup.Invoke_Scala(name, id) => | 
| 75441 
400e325a5416
clarified signature, based on hints by IntelliJ IDEA;
 wenzelm parents: 
75440diff
changeset | 331 |           def body(): Unit = {
 | 
| 77027 | 332 | val (tag, res) = Scala.function_body(session, name, msg.chunks) | 
| 72332 
319dd5c618a5
allow Scala function execution on separate thread: better reactivity, but potential overloading of the JVM;
 wenzelm parents: 
72294diff
changeset | 333 | result(id, tag, res) | 
| 
319dd5c618a5
allow Scala function execution on separate thread: better reactivity, but potential overloading of the JVM;
 wenzelm parents: 
72294diff
changeset | 334 | } | 
| 
319dd5c618a5
allow Scala function execution on separate thread: better reactivity, but potential overloading of the JVM;
 wenzelm parents: 
72294diff
changeset | 335 | val future = | 
| 73419 
22f3f2117ed7
clarified signature: function_thread is determined in Isabelle/Scala, not Isabelle/ML;
 wenzelm parents: 
73418diff
changeset | 336 |             if (Scala.function_thread(name)) {
 | 
| 75441 
400e325a5416
clarified signature, based on hints by IntelliJ IDEA;
 wenzelm parents: 
75440diff
changeset | 337 | Future.thread(name = Isabelle_Thread.make_name(base = "invoke_scala"))(body()) | 
| 72332 
319dd5c618a5
allow Scala function execution on separate thread: better reactivity, but potential overloading of the JVM;
 wenzelm parents: 
72294diff
changeset | 338 | } | 
| 75441 
400e325a5416
clarified signature, based on hints by IntelliJ IDEA;
 wenzelm parents: 
75440diff
changeset | 339 | else Future.fork(body()) | 
| 72332 
319dd5c618a5
allow Scala function execution on separate thread: better reactivity, but potential overloading of the JVM;
 wenzelm parents: 
72294diff
changeset | 340 | futures += (id -> future) | 
| 72157 | 341 | true | 
| 342 | case _ => false | |
| 56387 | 343 | } | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 344 | } | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 345 | |
| 75380 | 346 |     private def cancel_scala(msg: Prover.Protocol_Output): Boolean = synchronized {
 | 
| 72157 | 347 |       msg.properties match {
 | 
| 348 | case Markup.Cancel_Scala(id) => | |
| 349 |           futures.get(id) match {
 | |
| 350 | case Some(future) => cancel(id, future) | |
| 351 | case None => | |
| 352 | } | |
| 353 | true | |
| 354 | case _ => false | |
| 355 | } | |
| 356 | } | |
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 357 | |
| 75440 | 358 | override val functions: Session.Protocol_Functions = | 
| 72157 | 359 | List( | 
| 360 | Markup.Invoke_Scala.name -> invoke_scala, | |
| 361 | Markup.Cancel_Scala.name -> cancel_scala) | |
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 362 | } | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 363 | } | 
| 71871 
28def00726ca
more robust isabelle.Functions --- avoid Java reflection with unclear class/object treatment;
 wenzelm parents: 
71870diff
changeset | 364 | |
| 72193 | 365 | class Scala_Functions extends Scala.Functions( | 
| 366 | Scala.Echo, | |
| 367 | Scala.Sleep, | |
| 72194 | 368 | Scala.Toplevel, | 
| 75660 
45d3497c0baa
support for Isabelle/Scala/Java modules in Isabelle/ML;
 wenzelm parents: 
75654diff
changeset | 369 | Scala_Build.Scala_Fun, | 
| 75620 | 370 | Base64.Decode, | 
| 371 | Base64.Encode, | |
| 76351 
2cee31cd92f0
generic support for XZ and Zstd compression in Isabelle/Scala;
 wenzelm parents: 
75705diff
changeset | 372 | Compress.XZ_Compress, | 
| 
2cee31cd92f0
generic support for XZ and Zstd compression in Isabelle/Scala;
 wenzelm parents: 
75705diff
changeset | 373 | Compress.XZ_Uncompress, | 
| 
2cee31cd92f0
generic support for XZ and Zstd compression in Isabelle/Scala;
 wenzelm parents: 
75705diff
changeset | 374 | Compress.Zstd_Compress, | 
| 
2cee31cd92f0
generic support for XZ and Zstd compression in Isabelle/Scala;
 wenzelm parents: 
75705diff
changeset | 375 | Compress.Zstd_Uncompress, | 
| 72760 
042180540068
clarified protocol: Doc.check at run-time via Scala function;
 wenzelm parents: 
72756diff
changeset | 376 | Doc.Doc_Names, | 
| 72763 | 377 | Bibtex.Check_Database, | 
| 77028 
f5896dea6fce
more direct check of bibtex entries via Isabelle/Scala;
 wenzelm parents: 
77027diff
changeset | 378 | Bibtex.Session_Entries, | 
| 73314 
87403fde8cc3
more direct make_directory in ML and Scala, but ssh still requires perl for Windows UNC paths (see a5dbad753552);
 wenzelm parents: 
73228diff
changeset | 379 | Isabelle_System.Make_Directory, | 
| 73322 | 380 | Isabelle_System.Copy_Dir, | 
| 381 | Isabelle_System.Copy_File, | |
| 382 | Isabelle_System.Copy_File_Base, | |
| 73324 | 383 | Isabelle_System.Rm_Tree, | 
| 73323 | 384 | Isabelle_System.Download, | 
| 73523 
2cd23d587db9
further clarification of Isabelle distribution identification -- avoid odd patching of sources;
 wenzelm parents: 
73431diff
changeset | 385 | Isabelle_System.Isabelle_Id, | 
| 73418 
7d7d959547a1
support for SystemOnTPTP in Isabelle/ML and Isabelle/Scala (without perl);
 wenzelm parents: 
73367diff
changeset | 386 | Isabelle_Tool.Isabelle_Tools, | 
| 73431 
f27d7b12e8a4
support for SystemOnTPTP.run_system, with strict error following scripts/remote_atp;
 wenzelm parents: 
73419diff
changeset | 387 | isabelle.atp.SystemOnTPTP.List_Systems, | 
| 76514 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76351diff
changeset | 388 | isabelle.atp.SystemOnTPTP.Run_System, | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76351diff
changeset | 389 | Prismjs.Languages, | 
| 
2615cf68f6f4
ML support for the Prism.js syntax highlighter -- via Isabelle/Scala;
 wenzelm parents: 
76351diff
changeset | 390 | Prismjs.Tokenize) |