| author | fleury | 
| Mon, 16 Jun 2014 16:18:34 +0200 | |
| changeset 57256 | cf43583f9bb9 | 
| parent 56730 | e723f041b6d0 | 
| child 61556 | 0d4ee4168e41 | 
| permissions | -rw-r--r-- | 
| 43744 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 1 | /* Title: Pure/System/invoke_scala.scala | 
| 
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 | |
| 49173 
fa01a202399c
eliminated potentially confusing terminology of Scala "layer";
 wenzelm parents: 
44158diff
changeset | 4 | JVM method invocation service via Isabelle/Scala. | 
| 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 | |
| 43751 
8c7f69f1825b
proper InvocationTargetException.getCause for indirect exceptions;
 wenzelm parents: 
43748diff
changeset | 10 | import java.lang.reflect.{Method, Modifier, InvocationTargetException}
 | 
| 56730 
e723f041b6d0
tuned signature -- separate pool for JFuture tasks, which can be canceled;
 wenzelm parents: 
56667diff
changeset | 11 | import java.util.concurrent.{Future => JFuture}
 | 
| 
e723f041b6d0
tuned signature -- separate pool for JFuture tasks, which can be canceled;
 wenzelm parents: 
56667diff
changeset | 12 | |
| 43748 | 13 | import scala.util.matching.Regex | 
| 43744 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 14 | |
| 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 15 | |
| 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 16 | object Invoke_Scala | 
| 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 17 | {
 | 
| 43748 | 18 | /* method reflection */ | 
| 19 | ||
| 20 |   private val Ext = new Regex("(.*)\\.([^.]*)")
 | |
| 43744 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 21 |   private val STRING = Class.forName("java.lang.String")
 | 
| 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 22 | |
| 43748 | 23 | private def get_method(name: String): String => String = | 
| 24 |     name match {
 | |
| 25 | case Ext(class_name, method_name) => | |
| 26 | val m = | |
| 27 |           try { Class.forName(class_name).getMethod(method_name, STRING) }
 | |
| 28 |           catch {
 | |
| 43751 
8c7f69f1825b
proper InvocationTargetException.getCause for indirect exceptions;
 wenzelm parents: 
43748diff
changeset | 29 | case _: ClassNotFoundException | _: NoSuchMethodException => | 
| 
8c7f69f1825b
proper InvocationTargetException.getCause for indirect exceptions;
 wenzelm parents: 
43748diff
changeset | 30 |               error("No such method: " + quote(name))
 | 
| 43748 | 31 | } | 
| 32 |         if (!Modifier.isStatic(m.getModifiers)) error("Not at static method: " + m.toString)
 | |
| 43751 
8c7f69f1825b
proper InvocationTargetException.getCause for indirect exceptions;
 wenzelm parents: 
43748diff
changeset | 33 |         if (m.getReturnType != STRING) error("Bad method return type: " + m.toString)
 | 
| 43748 | 34 | |
| 43751 
8c7f69f1825b
proper InvocationTargetException.getCause for indirect exceptions;
 wenzelm parents: 
43748diff
changeset | 35 |         (arg: String) => {
 | 
| 
8c7f69f1825b
proper InvocationTargetException.getCause for indirect exceptions;
 wenzelm parents: 
43748diff
changeset | 36 |           try { m.invoke(null, arg).asInstanceOf[String] }
 | 
| 
8c7f69f1825b
proper InvocationTargetException.getCause for indirect exceptions;
 wenzelm parents: 
43748diff
changeset | 37 |           catch {
 | 
| 
8c7f69f1825b
proper InvocationTargetException.getCause for indirect exceptions;
 wenzelm parents: 
43748diff
changeset | 38 | case e: InvocationTargetException if e.getCause != null => | 
| 
8c7f69f1825b
proper InvocationTargetException.getCause for indirect exceptions;
 wenzelm parents: 
43748diff
changeset | 39 | throw e.getCause | 
| 
8c7f69f1825b
proper InvocationTargetException.getCause for indirect exceptions;
 wenzelm parents: 
43748diff
changeset | 40 | } | 
| 
8c7f69f1825b
proper InvocationTargetException.getCause for indirect exceptions;
 wenzelm parents: 
43748diff
changeset | 41 | } | 
| 43748 | 42 |       case _ => error("Malformed method name: " + quote(name))
 | 
| 43 | } | |
| 44 | ||
| 45 | ||
| 46 | /* method invocation */ | |
| 47 | ||
| 48 | object Tag extends Enumeration | |
| 43744 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 49 |   {
 | 
| 43748 | 50 |     val NULL = Value("0")
 | 
| 51 |     val OK = Value("1")
 | |
| 52 |     val ERROR = Value("2")
 | |
| 53 |     val FAIL = Value("3")
 | |
| 49470 | 54 |     val INTERRUPT = Value("4")
 | 
| 43748 | 55 | } | 
| 43744 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 56 | |
| 43748 | 57 | def method(name: String, arg: String): (Tag.Value, String) = | 
| 58 |     Exn.capture { get_method(name) } match {
 | |
| 59 | case Exn.Res(f) => | |
| 60 |         Exn.capture { f(arg) } match {
 | |
| 61 | case Exn.Res(null) => (Tag.NULL, "") | |
| 62 | case Exn.Res(res) => (Tag.OK, res) | |
| 56667 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 wenzelm parents: 
56387diff
changeset | 63 | case Exn.Exn(Exn.Interrupt()) => (Tag.INTERRUPT, "") | 
| 44158 | 64 | case Exn.Exn(e) => (Tag.ERROR, Exn.message(e)) | 
| 43748 | 65 | } | 
| 44158 | 66 | case Exn.Exn(e) => (Tag.FAIL, Exn.message(e)) | 
| 43748 | 67 | } | 
| 43744 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 68 | } | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 69 | |
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 70 | |
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 71 | /* protocol handler */ | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 72 | |
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 73 | class Invoke_Scala extends Session.Protocol_Handler | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 74 | {
 | 
| 56730 
e723f041b6d0
tuned signature -- separate pool for JFuture tasks, which can be canceled;
 wenzelm parents: 
56667diff
changeset | 75 | private var futures = Map.empty[String, JFuture[Unit]] | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 76 | |
| 56387 | 77 | private def fulfill(prover: Prover, id: String, tag: Invoke_Scala.Tag.Value, res: String): Unit = | 
| 78 | synchronized | |
| 79 |     {
 | |
| 80 |       if (futures.isDefinedAt(id)) {
 | |
| 81 |         prover.protocol_command("Invoke_Scala.fulfill", id, tag.toString, res)
 | |
| 82 | futures -= id | |
| 83 | } | |
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 84 | } | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 85 | |
| 56730 
e723f041b6d0
tuned signature -- separate pool for JFuture tasks, which can be canceled;
 wenzelm parents: 
56667diff
changeset | 86 | private def cancel(prover: Prover, id: String, future: JFuture[Unit]) | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 87 |   {
 | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 88 | future.cancel(true) | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 89 | fulfill(prover, id, Invoke_Scala.Tag.INTERRUPT, "") | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 90 | } | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 91 | |
| 56387 | 92 | private def invoke_scala(prover: Prover, msg: Prover.Protocol_Output): Boolean = synchronized | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 93 |   {
 | 
| 54442 
c39972ddd672
more specific Protocol_Output: empty message.body, main content via bytes/text;
 wenzelm parents: 
52582diff
changeset | 94 |     msg.properties match {
 | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 95 | case Markup.Invoke_Scala(name, id) => | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 96 | futures += (id -> | 
| 56730 
e723f041b6d0
tuned signature -- separate pool for JFuture tasks, which can be canceled;
 wenzelm parents: 
56667diff
changeset | 97 |           Simple_Thread.submit_task {
 | 
| 
e723f041b6d0
tuned signature -- separate pool for JFuture tasks, which can be canceled;
 wenzelm parents: 
56667diff
changeset | 98 | val (tag, result) = Invoke_Scala.method(name, msg.text) | 
| 
e723f041b6d0
tuned signature -- separate pool for JFuture tasks, which can be canceled;
 wenzelm parents: 
56667diff
changeset | 99 | fulfill(prover, id, tag, result) | 
| 
e723f041b6d0
tuned signature -- separate pool for JFuture tasks, which can be canceled;
 wenzelm parents: 
56667diff
changeset | 100 | }) | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 101 | true | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 102 | case _ => false | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 103 | } | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 104 | } | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 105 | |
| 56387 | 106 | private def cancel_scala(prover: Prover, msg: Prover.Protocol_Output): Boolean = synchronized | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 107 |   {
 | 
| 54442 
c39972ddd672
more specific Protocol_Output: empty message.body, main content via bytes/text;
 wenzelm parents: 
52582diff
changeset | 108 |     msg.properties match {
 | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 109 | case Markup.Cancel_Scala(id) => | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 110 |         futures.get(id) match {
 | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 111 | case Some(future) => cancel(prover, id, future) | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 112 | case None => | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 113 | } | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 114 | true | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 115 | case _ => false | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 116 | } | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 117 | } | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 118 | |
| 56387 | 119 | override def stop(prover: Prover): Unit = synchronized | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 120 |   {
 | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 121 | for ((id, future) <- futures) cancel(prover, id, future) | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 122 | futures = Map.empty | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 123 | } | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 124 | |
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 125 | val functions = Map( | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 126 | Markup.INVOKE_SCALA -> invoke_scala _, | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 127 | Markup.CANCEL_SCALA -> cancel_scala _) | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 128 | } | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 129 |