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