| author | wenzelm | 
| Sun, 09 Jun 2024 21:16:38 +0200 | |
| changeset 80313 | a828e47c867c | 
| parent 80300 | 152d6c58adb3 | 
| child 83311 | 0e40bd617b6c | 
| 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 = | 
| 80300 
152d6c58adb3
more informative exception output, with optional trace;
 wenzelm parents: 
75393diff
changeset | 12 |     error("Failed to initialize protocol handler: " + quote(name) + "\n" + Exn.print(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: 
71970diff
changeset | 23 |       try {
 | 
| 
065dcd80293e
provide protocol handlers via isabelle_system_service;
 wenzelm parents: 
71970diff
changeset | 24 |         if (handlers.isDefinedAt(name)) error("Duplicate protocol handler: " + name)
 | 
| 
065dcd80293e
provide protocol handlers via isabelle_system_service;
 wenzelm parents: 
71970diff
changeset | 25 |         else {
 | 
| 
065dcd80293e
provide protocol handlers via isabelle_system_service;
 wenzelm parents: 
71970diff
changeset | 26 | handler.init(session) | 
| 
065dcd80293e
provide protocol handlers via isabelle_system_service;
 wenzelm parents: 
71970diff
changeset | 27 | val dups = for ((a, _) <- handler.functions if functions.isDefinedAt(a)) yield a | 
| 
065dcd80293e
provide protocol handlers via isabelle_system_service;
 wenzelm parents: 
71970diff
changeset | 28 |           if (dups.nonEmpty) error("Duplicate protocol functions: " + commas_quote(dups))
 | 
| 
065dcd80293e
provide protocol handlers via isabelle_system_service;
 wenzelm parents: 
71970diff
changeset | 29 | copy(handlers = handlers + (name -> handler), functions = functions ++ handler.functions) | 
| 65214 | 30 | } | 
| 72156 
065dcd80293e
provide protocol handlers via isabelle_system_service;
 wenzelm parents: 
71970diff
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( | |
| 80300 
152d6c58adb3
more informative exception output, with optional trace;
 wenzelm parents: 
75393diff
changeset | 52 | "Failed invocation of protocol function: " + quote(a) + "\n" + Exn.print(exn)) | 
| 65214 | 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 | } |