| author | wenzelm | 
| Sat, 08 Oct 2016 10:59:38 +0200 | |
| changeset 64098 | 099518e8af2c | 
| parent 61561 | f35786faee6c | 
| child 64442 | 85adb337e32f | 
| 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 |   {
 | 
| 43748 | 49 |     val NULL = Value("0")
 | 
| 50 |     val OK = Value("1")
 | |
| 51 |     val ERROR = Value("2")
 | |
| 52 |     val FAIL = Value("3")
 | |
| 49470 | 53 |     val INTERRUPT = Value("4")
 | 
| 43748 | 54 | } | 
| 43744 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 55 | |
| 43748 | 56 | def method(name: String, arg: String): (Tag.Value, String) = | 
| 57 |     Exn.capture { get_method(name) } match {
 | |
| 58 | case Exn.Res(f) => | |
| 59 |         Exn.capture { f(arg) } match {
 | |
| 60 | case Exn.Res(null) => (Tag.NULL, "") | |
| 61 | case Exn.Res(res) => (Tag.OK, res) | |
| 56667 
65e84b0ef974
more abstract Exn.Interrupt and POSIX return code;
 wenzelm parents: 
56387diff
changeset | 62 | case Exn.Exn(Exn.Interrupt()) => (Tag.INTERRUPT, "") | 
| 44158 | 63 | case Exn.Exn(e) => (Tag.ERROR, Exn.message(e)) | 
| 43748 | 64 | } | 
| 44158 | 65 | case Exn.Exn(e) => (Tag.FAIL, Exn.message(e)) | 
| 43748 | 66 | } | 
| 43744 
2c7e1565b4a3
some support to invoke Scala methods under program control;
 wenzelm parents: diff
changeset | 67 | } | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 68 | |
| 
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 | /* protocol handler */ | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 71 | |
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 72 | class Invoke_Scala extends Session.Protocol_Handler | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 73 | {
 | 
| 61561 | 74 | 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 | 75 | |
| 56387 | 76 | private def fulfill(prover: Prover, id: String, tag: Invoke_Scala.Tag.Value, res: String): Unit = | 
| 77 | synchronized | |
| 78 |     {
 | |
| 79 |       if (futures.isDefinedAt(id)) {
 | |
| 80 |         prover.protocol_command("Invoke_Scala.fulfill", id, tag.toString, res)
 | |
| 81 | futures -= id | |
| 82 | } | |
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 83 | } | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 84 | |
| 61561 | 85 | private def cancel(prover: Prover, id: String, future: Future[Unit]) | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 86 |   {
 | 
| 61561 | 87 | future.cancel | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 88 | fulfill(prover, id, Invoke_Scala.Tag.INTERRUPT, "") | 
| 
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 | |
| 56387 | 91 | 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 | 92 |   {
 | 
| 54442 
c39972ddd672
more specific Protocol_Output: empty message.body, main content via bytes/text;
 wenzelm parents: 
52582diff
changeset | 93 |     msg.properties match {
 | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 94 | case Markup.Invoke_Scala(name, id) => | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 95 | futures += (id -> | 
| 61561 | 96 |           Future.fork {
 | 
| 56730 
e723f041b6d0
tuned signature -- separate pool for JFuture tasks, which can be canceled;
 wenzelm parents: 
56667diff
changeset | 97 | 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 | 98 | fulfill(prover, id, tag, result) | 
| 
e723f041b6d0
tuned signature -- separate pool for JFuture tasks, which can be canceled;
 wenzelm parents: 
56667diff
changeset | 99 | }) | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 100 | true | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 101 | case _ => false | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 102 | } | 
| 
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 | |
| 56387 | 105 | 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 | 106 |   {
 | 
| 54442 
c39972ddd672
more specific Protocol_Output: empty message.body, main content via bytes/text;
 wenzelm parents: 
52582diff
changeset | 107 |     msg.properties match {
 | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 108 | case Markup.Cancel_Scala(id) => | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 109 |         futures.get(id) match {
 | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 110 | case Some(future) => cancel(prover, id, future) | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 111 | case None => | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 112 | } | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 113 | true | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 114 | case _ => false | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 115 | } | 
| 
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 | |
| 56387 | 118 | override def stop(prover: Prover): Unit = synchronized | 
| 52111 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 119 |   {
 | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 120 | for ((id, future) <- futures) cancel(prover, id, future) | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 121 | futures = Map.empty | 
| 
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 | |
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 124 | val functions = Map( | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 125 | Markup.INVOKE_SCALA -> invoke_scala _, | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 126 | Markup.CANCEL_SCALA -> cancel_scala _) | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 127 | } | 
| 
1fd184eaa310
explicit management of Session.Protocol_Handlers, with protocol state and functions;
 wenzelm parents: 
49470diff
changeset | 128 |