author | wenzelm |
Thu, 06 Jun 2024 11:53:52 +0200 | |
changeset 80266 | d52be75ae60b |
parent 75393 | 87ebf5a50283 |
child 80300 | 152d6c58adb3 |
permissions | -rw-r--r-- |
65214 | 1 |
/* Title: Pure/PIDE/protocol_handlers.scala |
2 |
Author: Makarius |
|
3 |
||
4 |
Management of add-on protocol handlers for PIDE session. |
|
5 |
*/ |
|
6 |
||
7 |
package isabelle |
|
8 |
||
9 |
||
75393 | 10 |
object Protocol_Handlers { |
72217 | 11 |
private def err_handler(exn: Throwable, name: String): Nothing = |
12 |
error("Failed to initialize protocol handler: " + quote(name) + "\n" + Exn.message(exn)) |
|
65214 | 13 |
|
14 |
sealed case class State( |
|
65215 | 15 |
session: Session, |
65214 | 16 |
handlers: Map[String, Session.Protocol_Handler] = Map.empty, |
75393 | 17 |
functions: Map[String, Session.Protocol_Function] = Map.empty |
18 |
) { |
|
65214 | 19 |
def get(name: String): Option[Session.Protocol_Handler] = handlers.get(name) |
20 |
||
75393 | 21 |
def init(handler: Session.Protocol_Handler): State = { |
65214 | 22 |
val name = handler.getClass.getName |
72156
065dcd80293e
provide protocol handlers via isabelle_system_service;
wenzelm
parents:
71970
diff
changeset
|
23 |
try { |
065dcd80293e
provide protocol handlers via isabelle_system_service;
wenzelm
parents:
71970
diff
changeset
|
24 |
if (handlers.isDefinedAt(name)) error("Duplicate protocol handler: " + name) |
065dcd80293e
provide protocol handlers via isabelle_system_service;
wenzelm
parents:
71970
diff
changeset
|
25 |
else { |
065dcd80293e
provide protocol handlers via isabelle_system_service;
wenzelm
parents:
71970
diff
changeset
|
26 |
handler.init(session) |
065dcd80293e
provide protocol handlers via isabelle_system_service;
wenzelm
parents:
71970
diff
changeset
|
27 |
val dups = for ((a, _) <- handler.functions if functions.isDefinedAt(a)) yield a |
065dcd80293e
provide protocol handlers via isabelle_system_service;
wenzelm
parents:
71970
diff
changeset
|
28 |
if (dups.nonEmpty) error("Duplicate protocol functions: " + commas_quote(dups)) |
065dcd80293e
provide protocol handlers via isabelle_system_service;
wenzelm
parents:
71970
diff
changeset
|
29 |
copy(handlers = handlers + (name -> handler), functions = functions ++ handler.functions) |
65214 | 30 |
} |
72156
065dcd80293e
provide protocol handlers via isabelle_system_service;
wenzelm
parents:
71970
diff
changeset
|
31 |
} |
72217 | 32 |
catch { case exn: Throwable => err_handler(exn, name) } |
65214 | 33 |
} |
34 |
||
75393 | 35 |
def init(name: String): State = { |
72217 | 36 |
val handler = |
71734 | 37 |
try { |
72217 | 38 |
Class.forName(name).getDeclaredConstructor().newInstance() |
39 |
.asInstanceOf[Session.Protocol_Handler] |
|
71734 | 40 |
} |
72217 | 41 |
catch { case exn: Throwable => err_handler(exn, name) } |
42 |
init(handler) |
|
65214 | 43 |
} |
44 |
||
45 |
def invoke(msg: Prover.Protocol_Output): Boolean = |
|
46 |
msg.properties match { |
|
71673 | 47 |
case (Markup.FUNCTION, a) :: _ if functions.isDefinedAt(a) => |
65214 | 48 |
try { functions(a)(msg) } |
49 |
catch { |
|
50 |
case exn: Throwable => |
|
51 |
Output.error_message( |
|
52 |
"Failed invocation of protocol function: " + quote(a) + "\n" + Exn.message(exn)) |
|
53 |
false |
|
54 |
} |
|
55 |
case _ => false |
|
56 |
} |
|
57 |
||
75393 | 58 |
def exit(): State = { |
65219 | 59 |
for ((_, handler) <- handlers) handler.exit() |
65215 | 60 |
copy(handlers = Map.empty, functions = Map.empty) |
65214 | 61 |
} |
62 |
} |
|
63 |
||
65215 | 64 |
def init(session: Session): Protocol_Handlers = |
65 |
new Protocol_Handlers(session) |
|
65214 | 66 |
} |
67 |
||
75393 | 68 |
class Protocol_Handlers private(session: Session) { |
65215 | 69 |
private val state = Synchronized(Protocol_Handlers.State(session)) |
65214 | 70 |
|
72216 | 71 |
def prover_options(options: Options): Options = |
73359 | 72 |
state.value.handlers.foldLeft(options) { |
73 |
case (opts, (_, handler)) => handler.prover_options(opts) |
|
74 |
} |
|
72216 | 75 |
|
65219 | 76 |
def get(name: String): Option[Session.Protocol_Handler] = state.value.get(name) |
65315 | 77 |
def init(handler: Session.Protocol_Handler): Unit = state.change(_.init(handler)) |
78 |
def init(name: String): Unit = state.change(_.init(name)) |
|
65219 | 79 |
def invoke(msg: Prover.Protocol_Output): Boolean = state.value.invoke(msg) |
80 |
def exit(): Unit = state.change(_.exit()) |
|
65214 | 81 |
} |