src/Pure/PIDE/protocol_handlers.scala
author wenzelm
Mon, 13 Mar 2017 21:37:35 +0100
changeset 65214 a2ec0db555c7
child 65215 90a7876d6f4c
permissions -rw-r--r--
clarified modules;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
65214
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/PIDE/protocol_handlers.scala
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
     3
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
     4
Management of add-on protocol handlers for PIDE session.
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
     5
*/
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
     6
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
     7
package isabelle
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
     8
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
     9
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    10
object Protocol_Handlers
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    11
{
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    12
  private def bad_handler(exn: Throwable, name: String): Unit =
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    13
    Output.error_message(
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    14
      "Failed to initialize protocol handler: " + quote(name) + "\n" + Exn.message(exn))
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    15
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    16
  private val init_state = State()
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    17
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    18
  sealed case class State(
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    19
    handlers: Map[String, Session.Protocol_Handler] = Map.empty,
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    20
    functions: Map[String, Prover.Protocol_Output => Boolean] = Map.empty)
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    21
  {
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    22
    def get(name: String): Option[Session.Protocol_Handler] = handlers.get(name)
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    23
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    24
    def add(session: Session, prover: Prover, handler: Session.Protocol_Handler): State =
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    25
    {
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    26
      val name = handler.getClass.getName
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    27
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    28
      val (handlers1, functions1) =
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    29
        handlers.get(name) match {
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    30
          case Some(old_handler) =>
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    31
            Output.warning("Redefining protocol handler: " + name)
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    32
            old_handler.stop(prover)
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    33
            (handlers - name, functions -- old_handler.functions.keys)
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    34
          case None => (handlers, functions)
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    35
        }
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    36
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    37
      val (handlers2, functions2) =
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    38
        try {
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    39
          handler.start(session, prover)
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    40
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    41
          val new_functions =
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    42
            for ((a, f) <- handler.functions.toList) yield
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    43
              (a, (msg: Prover.Protocol_Output) => f(prover, msg))
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    44
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    45
          val dups = for ((a, _) <- new_functions if functions1.isDefinedAt(a)) yield a
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    46
          if (dups.nonEmpty) error("Duplicate protocol functions: " + commas_quote(dups))
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    47
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    48
          (handlers1 + (name -> handler), functions1 ++ new_functions)
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    49
        }
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    50
        catch {
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    51
          case exn: Throwable => bad_handler(exn, name); (handlers1, functions1)
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    52
        }
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    53
      State(handlers2, functions2)
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    54
    }
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    55
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    56
    def add(session: Session, prover: Prover, name: String): State =
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    57
    {
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    58
      val new_handler =
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    59
        try { Some(Class.forName(name).newInstance.asInstanceOf[Session.Protocol_Handler]) }
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    60
        catch { case exn: Throwable => bad_handler(exn, name); None }
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    61
      new_handler match {
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    62
        case Some(handler) => add(session, prover, handler)
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    63
        case None => this
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    64
      }
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    65
    }
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    66
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    67
    def invoke(msg: Prover.Protocol_Output): Boolean =
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    68
      msg.properties match {
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    69
        case Markup.Function(a) if functions.isDefinedAt(a) =>
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    70
          try { functions(a)(msg) }
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    71
          catch {
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    72
            case exn: Throwable =>
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    73
              Output.error_message(
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    74
                "Failed invocation of protocol function: " + quote(a) + "\n" + Exn.message(exn))
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    75
            false
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    76
          }
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    77
        case _ => false
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    78
      }
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    79
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    80
    def stop(prover: Prover): State =
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    81
    {
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    82
      for ((_, handler) <- handlers) handler.stop(prover)
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    83
      init_state
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    84
    }
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    85
  }
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    86
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    87
  def init(): Protocol_Handlers = new Protocol_Handlers()
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    88
}
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    89
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    90
class Protocol_Handlers private()
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    91
{
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    92
  private val state = Synchronized(Protocol_Handlers.init_state)
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    93
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    94
  def get(name: String): Option[Session.Protocol_Handler] =
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    95
    state.value.get(name)
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    96
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    97
  def add(session: Session, prover: Prover, handler: Session.Protocol_Handler): Unit =
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    98
    state.change(_.add(session, prover, handler))
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
    99
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
   100
  def add(session: Session, prover: Prover, name: String): Unit =
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
   101
    state.change(_.add(session, prover, name))
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
   102
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
   103
  def invoke(msg: Prover.Protocol_Output): Boolean =
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
   104
    state.value.invoke(msg)
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
   105
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
   106
  def stop(prover: Prover): Unit =
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
   107
    state.change(_.stop(prover))
a2ec0db555c7 clarified modules;
wenzelm
parents:
diff changeset
   108
}