src/Pure/Tools/debugger.scala
author wenzelm
Mon, 10 Aug 2015 14:14:49 +0200
changeset 60875 ee23c1d21ac3
parent 60869 878e32cf3131
child 60876 52edced9cce5
permissions -rw-r--r--
follow debugger focus;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
60749
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/Tools/debugger.scala
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
     3
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
     4
Interactive debugger for Isabelle/ML.
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
     5
*/
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
     6
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
     7
package isabelle
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
     8
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
     9
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
    10
object Debugger
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
    11
{
60834
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
    12
  /* global state */
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
    13
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    14
  sealed case class Debug_State(
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    15
    pos: Position.T,
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    16
    function: String)
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    17
60835
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    18
  sealed case class State(
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    19
    session: Session = new Session(Resources.empty),
60875
ee23c1d21ac3 follow debugger focus;
wenzelm
parents: 60869
diff changeset
    20
    focus: Option[Position.T] = None,  // position of active GUI component
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    21
    threads: Map[String, List[Debug_State]] = Map.empty,  // thread name ~> stack of debug states
60834
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
    22
    output: Map[String, Command.Results] = Map.empty)  // thread name ~> output messages
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
    23
  {
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    24
    def set_session(new_session: Session): State =
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    25
      copy(session = new_session)
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    26
60875
ee23c1d21ac3 follow debugger focus;
wenzelm
parents: 60869
diff changeset
    27
    def set_focus(new_focus: Option[Position.T]): State =
ee23c1d21ac3 follow debugger focus;
wenzelm
parents: 60869
diff changeset
    28
      copy(focus = new_focus)
ee23c1d21ac3 follow debugger focus;
wenzelm
parents: 60869
diff changeset
    29
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    30
    def get_thread(thread_name: String): List[Debug_State] =
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    31
      threads.getOrElse(thread_name, Nil)
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    32
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    33
    def update_thread(thread_name: String, debug_states: List[Debug_State]): State =
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    34
      copy(threads = threads + (thread_name -> debug_states))
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    35
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    36
    def get_output(thread_name: String): Command.Results =
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    37
      output.getOrElse(thread_name, Command.Results.empty)
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    38
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    39
    def add_output(thread_name: String, entry: Command.Results.Entry): State =
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    40
      copy(output = output + (thread_name -> (get_output(thread_name) + entry)))
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    41
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    42
    def clear_output(thread_name: String): State =
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    43
      copy(output = output - thread_name)
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    44
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    45
    def purge(thread_name: String): State =
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    46
      if (get_thread(thread_name).isEmpty)
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    47
        copy(threads = threads - thread_name, output = output - thread_name)
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    48
      else this
60834
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
    49
  }
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
    50
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
    51
  private val global_state = Synchronized(State())
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
    52
  def current_state(): State = global_state.value
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
    53
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
    54
60835
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    55
  /* protocol handler */
60749
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
    56
60835
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    57
  sealed case class Update(thread_names: Set[String])
60749
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
    58
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
    59
  class Handler extends Session.Protocol_Handler
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
    60
  {
60835
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    61
    private var updated = Set.empty[String]
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    62
    private val delay_update =
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    63
      Simple_Thread.delay_first(current_state().session.output_delay) {
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    64
        current_state().session.debugger_updates.post(Update(updated))
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    65
        updated = Set.empty
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    66
      }
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    67
    private def update(name: String)
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    68
    {
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    69
      updated += name
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    70
      delay_update.invoke()
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    71
    }
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    72
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    73
    private def debugger_state(prover: Prover, msg: Prover.Protocol_Output): Boolean =
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    74
    {
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    75
      msg.properties match {
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    76
        case Markup.Debugger_State(thread_name) =>
60863
21d70681ec05 proper Symbol.decode/encode;
wenzelm
parents: 60857
diff changeset
    77
          val msg_body =
21d70681ec05 proper Symbol.decode/encode;
wenzelm
parents: 60857
diff changeset
    78
            YXML.parse_body_failsafe(Symbol.decode(UTF8.decode_permissive(msg.bytes)))
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    79
          val debug_states =
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    80
          {
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    81
            import XML.Decode._
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    82
            list(pair(properties, Symbol.decode_string))(msg_body).map({
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    83
              case (pos, function) => Debug_State(pos, function)
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    84
            })
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    85
          }
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    86
          global_state.change(_.update_thread(thread_name, debug_states))
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    87
          update(thread_name)
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    88
          true
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    89
        case _ => false
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    90
      }
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    91
    }
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    92
60830
f56e189350b2 separate channel for debugger output;
wenzelm
parents: 60829
diff changeset
    93
    private def debugger_output(prover: Prover, msg: Prover.Protocol_Output): Boolean =
f56e189350b2 separate channel for debugger output;
wenzelm
parents: 60829
diff changeset
    94
    {
f56e189350b2 separate channel for debugger output;
wenzelm
parents: 60829
diff changeset
    95
      msg.properties match {
60835
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    96
        case Markup.Debugger_Output(thread_name) =>
60834
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
    97
          val msg_body =
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
    98
            prover.xml_cache.body(
60863
21d70681ec05 proper Symbol.decode/encode;
wenzelm
parents: 60857
diff changeset
    99
              YXML.parse_body_failsafe(Symbol.decode(UTF8.decode_permissive(msg.bytes))))
60834
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
   100
          msg_body match {
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
   101
            case List(XML.Elem(Markup(name, props @ Markup.Serial(i)), body)) =>
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
   102
              val message = XML.Elem(Markup(Markup.message(name), props), body)
60835
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
   103
              global_state.change(_.add_output(thread_name, i -> message))
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
   104
              update(thread_name)
60834
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
   105
              true
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
   106
            case _ => false
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
   107
          }
60830
f56e189350b2 separate channel for debugger output;
wenzelm
parents: 60829
diff changeset
   108
        case _ => false
f56e189350b2 separate channel for debugger output;
wenzelm
parents: 60829
diff changeset
   109
      }
f56e189350b2 separate channel for debugger output;
wenzelm
parents: 60829
diff changeset
   110
    }
f56e189350b2 separate channel for debugger output;
wenzelm
parents: 60829
diff changeset
   111
f56e189350b2 separate channel for debugger output;
wenzelm
parents: 60829
diff changeset
   112
    val functions =
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   113
      Map(
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   114
        Markup.DEBUGGER_STATE -> debugger_state _,
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   115
        Markup.DEBUGGER_OUTPUT -> debugger_output _)
60749
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
   116
  }
60765
e43e71a75838 support for ML debugger;
wenzelm
parents: 60749
diff changeset
   117
e43e71a75838 support for ML debugger;
wenzelm
parents: 60749
diff changeset
   118
e43e71a75838 support for ML debugger;
wenzelm
parents: 60749
diff changeset
   119
  /* protocol commands */
e43e71a75838 support for ML debugger;
wenzelm
parents: 60749
diff changeset
   120
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   121
  def init(session: Session)
60835
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
   122
  {
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   123
    global_state.change(_.set_session(session))
60835
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
   124
    current_state().session.protocol_command("Debugger.init")
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
   125
  }
60765
e43e71a75838 support for ML debugger;
wenzelm
parents: 60749
diff changeset
   126
60875
ee23c1d21ac3 follow debugger focus;
wenzelm
parents: 60869
diff changeset
   127
  def focus(new_focus: Option[Position.T]): Boolean =
ee23c1d21ac3 follow debugger focus;
wenzelm
parents: 60869
diff changeset
   128
    global_state.change_result(state => (state.focus != new_focus, state.set_focus(new_focus)))
ee23c1d21ac3 follow debugger focus;
wenzelm
parents: 60869
diff changeset
   129
60854
8f45dd297357 more controls;
wenzelm
parents: 60842
diff changeset
   130
  def cancel(thread_name: String): Unit =
8f45dd297357 more controls;
wenzelm
parents: 60842
diff changeset
   131
    current_state().session.protocol_command("Debugger.cancel", thread_name)
60765
e43e71a75838 support for ML debugger;
wenzelm
parents: 60749
diff changeset
   132
60854
8f45dd297357 more controls;
wenzelm
parents: 60842
diff changeset
   133
  def input(thread_name: String, msg: String*): Unit =
8f45dd297357 more controls;
wenzelm
parents: 60842
diff changeset
   134
    current_state().session.protocol_command("Debugger.input", (thread_name :: msg.toList):_*)
8f45dd297357 more controls;
wenzelm
parents: 60842
diff changeset
   135
60869
878e32cf3131 more single stepping;
wenzelm
parents: 60863
diff changeset
   136
  def step(thread_name: String): Unit = input(thread_name, "step")
878e32cf3131 more single stepping;
wenzelm
parents: 60863
diff changeset
   137
  def step_over(thread_name: String): Unit = input(thread_name, "step_over")
878e32cf3131 more single stepping;
wenzelm
parents: 60863
diff changeset
   138
  def step_out(thread_name: String): Unit = input(thread_name, "step_out")
60854
8f45dd297357 more controls;
wenzelm
parents: 60842
diff changeset
   139
  def continue(thread_name: String): Unit = input(thread_name, "continue")
60856
eb21ae05ec43 clarified thread state;
wenzelm
parents: 60854
diff changeset
   140
60857
4c18d8e4fe14 clarified debugger loop;
wenzelm
parents: 60856
diff changeset
   141
  def eval(thread_name: String, index: Int, SML: Boolean, context: String, expression: String): Unit =
60856
eb21ae05ec43 clarified thread state;
wenzelm
parents: 60854
diff changeset
   142
  {
60857
4c18d8e4fe14 clarified debugger loop;
wenzelm
parents: 60856
diff changeset
   143
    input(thread_name, "eval",
60863
21d70681ec05 proper Symbol.decode/encode;
wenzelm
parents: 60857
diff changeset
   144
      index.toString, SML.toString, Symbol.encode(context), Symbol.encode(expression))
60856
eb21ae05ec43 clarified thread state;
wenzelm
parents: 60854
diff changeset
   145
  }
60749
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
   146
}