src/Pure/Tools/debugger.scala
author wenzelm
Tue, 14 Mar 2017 00:09:15 +0100
changeset 65219 ed4b47b8c7dc
parent 65218 102b8e092860
child 65222 fb8253564483
permissions -rw-r--r--
misc tuning and simplification;
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
61016
wenzelm
parents: 61014
diff changeset
    10
import scala.collection.immutable.SortedMap
wenzelm
parents: 61014
diff changeset
    11
wenzelm
parents: 61014
diff changeset
    12
60749
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
    13
object Debugger
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
    14
{
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
    15
  /* thread context */
60834
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
    16
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
    17
  case object Update
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
    18
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
    19
  sealed case class Debug_State(pos: Position.T, function: String)
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
    20
  type Threads = SortedMap[String, List[Debug_State]]
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    21
61010
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    22
  sealed case class Context(thread_name: String, debug_states: List[Debug_State], index: Int = 0)
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    23
  {
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    24
    def size: Int = debug_states.length + 1
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    25
    def reset: Context = copy(index = 0)
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    26
    def select(i: Int) = copy(index = i + 1)
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    27
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    28
    def thread_state: Option[Debug_State] = debug_states.headOption
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    29
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    30
    def stack_state: Option[Debug_State] =
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    31
      if (1 <= index && index <= debug_states.length)
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    32
        Some(debug_states(index - 1))
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    33
      else None
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    34
61014
39f67bb4e609 maintain per-thread focus context;
wenzelm
parents: 61011
diff changeset
    35
    def debug_index: Option[Int] =
61010
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    36
      if (stack_state.isDefined) Some(index - 1)
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    37
      else if (debug_states.nonEmpty) Some(0)
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    38
      else None
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    39
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    40
    def debug_state: Option[Debug_State] = stack_state orElse thread_state
61014
39f67bb4e609 maintain per-thread focus context;
wenzelm
parents: 61011
diff changeset
    41
    def debug_position: Option[Position.T] = debug_state.map(_.pos)
61010
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    42
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    43
    override def toString: String =
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    44
      stack_state match {
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    45
        case None => thread_name
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    46
        case Some(d) => d.function
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    47
      }
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    48
  }
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    49
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
    50
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
    51
  /* debugger state */
61016
wenzelm
parents: 61014
diff changeset
    52
60835
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
    53
  sealed case class State(
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
    54
    session: Session,
60932
13ee73f57c85 allow to break running threads at next possible breakpoint (simplified version of former option, see f3039309702e);
wenzelm
parents: 60912
diff changeset
    55
    active: Int = 0,  // active views
13ee73f57c85 allow to break running threads at next possible breakpoint (simplified version of former option, see f3039309702e);
wenzelm
parents: 60912
diff changeset
    56
    break: Boolean = false,  // break at next possible breakpoint
13ee73f57c85 allow to break running threads at next possible breakpoint (simplified version of former option, see f3039309702e);
wenzelm
parents: 60912
diff changeset
    57
    active_breakpoints: Set[Long] = Set.empty,  // explicit breakpoint state
61016
wenzelm
parents: 61014
diff changeset
    58
    threads: Threads = SortedMap.empty,  // thread name ~> stack of debug states
61014
39f67bb4e609 maintain per-thread focus context;
wenzelm
parents: 61011
diff changeset
    59
    focus: Map[String, Context] = Map.empty,  // thread name ~> focus
60834
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
    60
    output: Map[String, Command.Results] = Map.empty)  // thread name ~> output messages
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
    61
  {
60932
13ee73f57c85 allow to break running threads at next possible breakpoint (simplified version of former option, see f3039309702e);
wenzelm
parents: 60912
diff changeset
    62
    def set_break(b: Boolean): State = copy(break = b)
13ee73f57c85 allow to break running threads at next possible breakpoint (simplified version of former option, see f3039309702e);
wenzelm
parents: 60912
diff changeset
    63
60910
79abcf48c377 clarified init/exit vs. session phase;
wenzelm
parents: 60903
diff changeset
    64
    def is_active: Boolean = active > 0 && session.is_ready
60898
a3fcde62df10 misc tuning and clarification;
wenzelm
parents: 60897
diff changeset
    65
    def inc_active: State = copy(active = active + 1)
a3fcde62df10 misc tuning and clarification;
wenzelm
parents: 60897
diff changeset
    66
    def dec_active: State = copy(active = active - 1)
60876
52edced9cce5 rendering for debugger/breakpoint active state;
wenzelm
parents: 60875
diff changeset
    67
60880
fa958e24ff24 set breakpoint state on ML side, relying on stable situation within the PIDE editing queue;
wenzelm
parents: 60878
diff changeset
    68
    def toggle_breakpoint(breakpoint: Long): (Boolean, State) =
60876
52edced9cce5 rendering for debugger/breakpoint active state;
wenzelm
parents: 60875
diff changeset
    69
    {
52edced9cce5 rendering for debugger/breakpoint active state;
wenzelm
parents: 60875
diff changeset
    70
      val active_breakpoints1 =
60880
fa958e24ff24 set breakpoint state on ML side, relying on stable situation within the PIDE editing queue;
wenzelm
parents: 60878
diff changeset
    71
        if (active_breakpoints(breakpoint)) active_breakpoints - breakpoint
fa958e24ff24 set breakpoint state on ML side, relying on stable situation within the PIDE editing queue;
wenzelm
parents: 60878
diff changeset
    72
      else active_breakpoints + breakpoint
fa958e24ff24 set breakpoint state on ML side, relying on stable situation within the PIDE editing queue;
wenzelm
parents: 60878
diff changeset
    73
      (active_breakpoints1(breakpoint), copy(active_breakpoints = active_breakpoints1))
60876
52edced9cce5 rendering for debugger/breakpoint active state;
wenzelm
parents: 60875
diff changeset
    74
    }
52edced9cce5 rendering for debugger/breakpoint active state;
wenzelm
parents: 60875
diff changeset
    75
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    76
    def get_thread(thread_name: String): List[Debug_State] =
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    77
      threads.getOrElse(thread_name, Nil)
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    78
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    79
    def update_thread(thread_name: String, debug_states: List[Debug_State]): State =
61019
7ce030f14aa9 reset focus after thread update (with new debug_states);
wenzelm
parents: 61018
diff changeset
    80
    {
7ce030f14aa9 reset focus after thread update (with new debug_states);
wenzelm
parents: 61018
diff changeset
    81
      val threads1 =
7ce030f14aa9 reset focus after thread update (with new debug_states);
wenzelm
parents: 61018
diff changeset
    82
        if (debug_states.nonEmpty) threads + (thread_name -> debug_states)
7ce030f14aa9 reset focus after thread update (with new debug_states);
wenzelm
parents: 61018
diff changeset
    83
        else threads - thread_name
7ce030f14aa9 reset focus after thread update (with new debug_states);
wenzelm
parents: 61018
diff changeset
    84
      val focus1 =
7ce030f14aa9 reset focus after thread update (with new debug_states);
wenzelm
parents: 61018
diff changeset
    85
        focus.get(thread_name) match {
7ce030f14aa9 reset focus after thread update (with new debug_states);
wenzelm
parents: 61018
diff changeset
    86
          case Some(c) if debug_states.nonEmpty =>
7ce030f14aa9 reset focus after thread update (with new debug_states);
wenzelm
parents: 61018
diff changeset
    87
            focus + (thread_name -> Context(thread_name, debug_states))
7ce030f14aa9 reset focus after thread update (with new debug_states);
wenzelm
parents: 61018
diff changeset
    88
          case _ => focus - thread_name
7ce030f14aa9 reset focus after thread update (with new debug_states);
wenzelm
parents: 61018
diff changeset
    89
        }
7ce030f14aa9 reset focus after thread update (with new debug_states);
wenzelm
parents: 61018
diff changeset
    90
      copy(threads = threads1, focus = focus1)
7ce030f14aa9 reset focus after thread update (with new debug_states);
wenzelm
parents: 61018
diff changeset
    91
    }
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    92
61014
39f67bb4e609 maintain per-thread focus context;
wenzelm
parents: 61011
diff changeset
    93
    def set_focus(c: Context): State = copy(focus = focus + (c.thread_name -> c))
39f67bb4e609 maintain per-thread focus context;
wenzelm
parents: 61011
diff changeset
    94
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    95
    def get_output(thread_name: String): Command.Results =
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    96
      output.getOrElse(thread_name, Command.Results.empty)
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    97
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    98
    def add_output(thread_name: String, entry: Command.Results.Entry): State =
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
    99
      copy(output = output + (thread_name -> (get_output(thread_name) + entry)))
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   100
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   101
    def clear_output(thread_name: String): State =
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   102
      copy(output = output - thread_name)
60834
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
   103
  }
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
   104
60902
9f185acfdcb8 clarified events;
wenzelm
parents: 60901
diff changeset
   105
9f185acfdcb8 clarified events;
wenzelm
parents: 60901
diff changeset
   106
  /* protocol handler */
9f185acfdcb8 clarified events;
wenzelm
parents: 60901
diff changeset
   107
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   108
  def get(session: Session): Option[Debugger] =
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   109
    session.get_protocol_handler("isabelle.Debugger$Handler") match {
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   110
      case Some(handler: Handler) => handler.get_debugger
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   111
      case _ => None
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   112
    }
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   113
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   114
  def apply(session: Session): Debugger =
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   115
    get(session) getOrElse error("Debugger not initialized")
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   116
60749
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
   117
  class Handler extends Session.Protocol_Handler
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
   118
  {
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   119
    private val _debugger_ = Synchronized[Option[Debugger]](None)
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   120
    def get_debugger: Option[Debugger] = _debugger_.value
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   121
    def the_debugger: Debugger = get_debugger getOrElse error("Debugger not initialized")
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   122
65219
ed4b47b8c7dc misc tuning and simplification;
wenzelm
parents: 65218
diff changeset
   123
    override def init(session: Session)
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   124
    {
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   125
      _debugger_.change(
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   126
        {
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   127
          case None => Some(new Debugger(session))
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   128
          case Some(_) => error("Debugger already initialized")
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   129
        })
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   130
    }
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   131
65219
ed4b47b8c7dc misc tuning and simplification;
wenzelm
parents: 65218
diff changeset
   132
    private def debugger_state(msg: Prover.Protocol_Output): Boolean =
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   133
    {
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   134
      msg.properties match {
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   135
        case Markup.Debugger_State(thread_name) =>
60863
21d70681ec05 proper Symbol.decode/encode;
wenzelm
parents: 60857
diff changeset
   136
          val msg_body =
21d70681ec05 proper Symbol.decode/encode;
wenzelm
parents: 60857
diff changeset
   137
            YXML.parse_body_failsafe(Symbol.decode(UTF8.decode_permissive(msg.bytes)))
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   138
          val debug_states =
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   139
          {
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   140
            import XML.Decode._
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   141
            list(pair(properties, Symbol.decode_string))(msg_body).map({
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   142
              case (pos, function) => Debug_State(pos, function)
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   143
            })
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   144
          }
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   145
          the_debugger.update_thread(thread_name, debug_states)
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   146
          true
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   147
        case _ => false
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   148
      }
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   149
    }
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   150
65219
ed4b47b8c7dc misc tuning and simplification;
wenzelm
parents: 65218
diff changeset
   151
    private def debugger_output(msg: Prover.Protocol_Output): Boolean =
60830
f56e189350b2 separate channel for debugger output;
wenzelm
parents: 60829
diff changeset
   152
    {
f56e189350b2 separate channel for debugger output;
wenzelm
parents: 60829
diff changeset
   153
      msg.properties match {
60835
6512bb0b1ff4 clarified management of (single) session;
wenzelm
parents: 60834
diff changeset
   154
        case Markup.Debugger_Output(thread_name) =>
65217
wenzelm
parents: 65213
diff changeset
   155
          YXML.parse_body_failsafe(Symbol.decode(UTF8.decode_permissive(msg.bytes))) match {
60834
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
   156
            case List(XML.Elem(Markup(name, props @ Markup.Serial(i)), body)) =>
65218
102b8e092860 more explicit Session.xml_cache;
wenzelm
parents: 65217
diff changeset
   157
              val debugger = the_debugger
102b8e092860 more explicit Session.xml_cache;
wenzelm
parents: 65217
diff changeset
   158
              val message = XML.Elem(Markup(Markup.message(name), props), body)
102b8e092860 more explicit Session.xml_cache;
wenzelm
parents: 65217
diff changeset
   159
              debugger.add_output(thread_name, i -> debugger.session.xml_cache.elem(message))
60834
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
   160
              true
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
   161
            case _ => false
781f1168d31e maintain debugger output messages;
wenzelm
parents: 60830
diff changeset
   162
          }
60830
f56e189350b2 separate channel for debugger output;
wenzelm
parents: 60829
diff changeset
   163
        case _ => false
f56e189350b2 separate channel for debugger output;
wenzelm
parents: 60829
diff changeset
   164
      }
f56e189350b2 separate channel for debugger output;
wenzelm
parents: 60829
diff changeset
   165
    }
f56e189350b2 separate channel for debugger output;
wenzelm
parents: 60829
diff changeset
   166
f56e189350b2 separate channel for debugger output;
wenzelm
parents: 60829
diff changeset
   167
    val functions =
65219
ed4b47b8c7dc misc tuning and simplification;
wenzelm
parents: 65218
diff changeset
   168
      List(
60842
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   169
        Markup.DEBUGGER_STATE -> debugger_state _,
5510c8444bc4 protocol support for thread debugger state;
wenzelm
parents: 60835
diff changeset
   170
        Markup.DEBUGGER_OUTPUT -> debugger_output _)
60749
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
   171
  }
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   172
}
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   173
65218
102b8e092860 more explicit Session.xml_cache;
wenzelm
parents: 65217
diff changeset
   174
class Debugger private(val session: Session)
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   175
{
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   176
  /* debugger state */
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   177
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   178
  private val state = Synchronized(Debugger.State(session))
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   179
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   180
  private val delay_update =
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   181
    Standard_Thread.delay_first(session.output_delay) {
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   182
      session.debugger_updates.post(Debugger.Update)
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   183
    }
60765
e43e71a75838 support for ML debugger;
wenzelm
parents: 60749
diff changeset
   184
e43e71a75838 support for ML debugger;
wenzelm
parents: 60749
diff changeset
   185
e43e71a75838 support for ML debugger;
wenzelm
parents: 60749
diff changeset
   186
  /* protocol commands */
e43e71a75838 support for ML debugger;
wenzelm
parents: 60749
diff changeset
   187
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   188
  def update_thread(thread_name: String, debug_states: List[Debugger.Debug_State])
60910
79abcf48c377 clarified init/exit vs. session phase;
wenzelm
parents: 60903
diff changeset
   189
  {
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   190
    state.change(_.update_thread(thread_name, debug_states))
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   191
    delay_update.invoke()
60910
79abcf48c377 clarified init/exit vs. session phase;
wenzelm
parents: 60903
diff changeset
   192
  }
79abcf48c377 clarified init/exit vs. session phase;
wenzelm
parents: 60903
diff changeset
   193
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   194
  def add_output(thread_name: String, entry: Command.Results.Entry)
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   195
  {
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   196
    state.change(_.add_output(thread_name, entry))
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   197
    delay_update.invoke()
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   198
  }
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   199
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   200
  def is_active(): Boolean = state.value.is_active
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   201
60910
79abcf48c377 clarified init/exit vs. session phase;
wenzelm
parents: 60903
diff changeset
   202
  def init(): Unit =
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   203
    state.change(st =>
60889
7f210887cc4e init/exit depending on active debugger panels;
wenzelm
parents: 60888
diff changeset
   204
    {
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   205
      val st1 = st.inc_active
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   206
      if (!st.is_active && st1.is_active)
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   207
        session.protocol_command("Debugger.init")
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   208
      st1
60889
7f210887cc4e init/exit depending on active debugger panels;
wenzelm
parents: 60888
diff changeset
   209
    })
7f210887cc4e init/exit depending on active debugger panels;
wenzelm
parents: 60888
diff changeset
   210
60910
79abcf48c377 clarified init/exit vs. session phase;
wenzelm
parents: 60903
diff changeset
   211
  def exit(): Unit =
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   212
    state.change(st =>
60889
7f210887cc4e init/exit depending on active debugger panels;
wenzelm
parents: 60888
diff changeset
   213
    {
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   214
      val st1 = st.dec_active
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   215
      if (st.is_active && !st1.is_active)
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   216
        session.protocol_command("Debugger.exit")
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   217
      st1
60889
7f210887cc4e init/exit depending on active debugger panels;
wenzelm
parents: 60888
diff changeset
   218
    })
60876
52edced9cce5 rendering for debugger/breakpoint active state;
wenzelm
parents: 60875
diff changeset
   219
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   220
  def is_break(): Boolean = state.value.break
60932
13ee73f57c85 allow to break running threads at next possible breakpoint (simplified version of former option, see f3039309702e);
wenzelm
parents: 60912
diff changeset
   221
  def set_break(b: Boolean)
13ee73f57c85 allow to break running threads at next possible breakpoint (simplified version of former option, see f3039309702e);
wenzelm
parents: 60912
diff changeset
   222
  {
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   223
    state.change(st => {
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   224
      val st1 = st.set_break(b)
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   225
      session.protocol_command("Debugger.break", b.toString)
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   226
      st1
60932
13ee73f57c85 allow to break running threads at next possible breakpoint (simplified version of former option, see f3039309702e);
wenzelm
parents: 60912
diff changeset
   227
    })
13ee73f57c85 allow to break running threads at next possible breakpoint (simplified version of former option, see f3039309702e);
wenzelm
parents: 60912
diff changeset
   228
    delay_update.invoke()
13ee73f57c85 allow to break running threads at next possible breakpoint (simplified version of former option, see f3039309702e);
wenzelm
parents: 60912
diff changeset
   229
  }
13ee73f57c85 allow to break running threads at next possible breakpoint (simplified version of former option, see f3039309702e);
wenzelm
parents: 60912
diff changeset
   230
60882
45bfd18835f1 tuned signature;
wenzelm
parents: 60880
diff changeset
   231
  def active_breakpoint_state(breakpoint: Long): Option[Boolean] =
60876
52edced9cce5 rendering for debugger/breakpoint active state;
wenzelm
parents: 60875
diff changeset
   232
  {
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   233
    val st = state.value
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   234
    if (st.is_active) Some(st.active_breakpoints(breakpoint)) else None
60876
52edced9cce5 rendering for debugger/breakpoint active state;
wenzelm
parents: 60875
diff changeset
   235
  }
52edced9cce5 rendering for debugger/breakpoint active state;
wenzelm
parents: 60875
diff changeset
   236
60882
45bfd18835f1 tuned signature;
wenzelm
parents: 60880
diff changeset
   237
  def breakpoint_state(breakpoint: Long): Boolean =
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   238
    state.value.active_breakpoints(breakpoint)
60882
45bfd18835f1 tuned signature;
wenzelm
parents: 60880
diff changeset
   239
60880
fa958e24ff24 set breakpoint state on ML side, relying on stable situation within the PIDE editing queue;
wenzelm
parents: 60878
diff changeset
   240
  def toggle_breakpoint(command: Command, breakpoint: Long)
60878
1f0d2bbcf38b added action to toggle breakpoints (on editor side);
wenzelm
parents: 60876
diff changeset
   241
  {
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   242
    state.change(st =>
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   243
      {
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   244
        val (breakpoint_state, st1) = st.toggle_breakpoint(breakpoint)
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   245
        session.protocol_command(
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   246
          "Debugger.breakpoint",
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   247
          Symbol.encode(command.node_name.node),
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   248
          Document_ID(command.id),
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   249
          Value.Long(breakpoint),
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   250
          Value.Boolean(breakpoint_state))
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   251
        st1
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   252
      })
60878
1f0d2bbcf38b added action to toggle breakpoints (on editor side);
wenzelm
parents: 60876
diff changeset
   253
  }
60876
52edced9cce5 rendering for debugger/breakpoint active state;
wenzelm
parents: 60875
diff changeset
   254
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   255
  def status(focus: Option[Debugger.Context]): (Debugger.Threads, List[XML.Tree]) =
61018
32cc7d219c38 atomic Debugger.status;
wenzelm
parents: 61016
diff changeset
   256
  {
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   257
    val st = state.value
61018
32cc7d219c38 atomic Debugger.status;
wenzelm
parents: 61016
diff changeset
   258
    val output =
32cc7d219c38 atomic Debugger.status;
wenzelm
parents: 61016
diff changeset
   259
      focus match {
32cc7d219c38 atomic Debugger.status;
wenzelm
parents: 61016
diff changeset
   260
        case None => Nil
32cc7d219c38 atomic Debugger.status;
wenzelm
parents: 61016
diff changeset
   261
        case Some(c) =>
32cc7d219c38 atomic Debugger.status;
wenzelm
parents: 61016
diff changeset
   262
          (for {
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   263
            (thread_name, results) <- st.output
61018
32cc7d219c38 atomic Debugger.status;
wenzelm
parents: 61016
diff changeset
   264
            if thread_name == c.thread_name
32cc7d219c38 atomic Debugger.status;
wenzelm
parents: 61016
diff changeset
   265
            (_, tree) <- results.iterator
32cc7d219c38 atomic Debugger.status;
wenzelm
parents: 61016
diff changeset
   266
          } yield tree).toList
32cc7d219c38 atomic Debugger.status;
wenzelm
parents: 61016
diff changeset
   267
      }
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   268
    (st.threads, output)
61018
32cc7d219c38 atomic Debugger.status;
wenzelm
parents: 61016
diff changeset
   269
  }
61011
018b0c996b54 more explicit debugger caret rendering;
wenzelm
parents: 61010
diff changeset
   270
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   271
  def focus(): List[Debugger.Context] = state.value.focus.toList.map(_._2)
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   272
  def set_focus(c: Debugger.Context)
61008
b88b8227e1a3 proper GUI event;
wenzelm
parents: 61007
diff changeset
   273
  {
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   274
    state.change(_.set_focus(c))
61008
b88b8227e1a3 proper GUI event;
wenzelm
parents: 61007
diff changeset
   275
    delay_update.invoke()
b88b8227e1a3 proper GUI event;
wenzelm
parents: 61007
diff changeset
   276
  }
60875
ee23c1d21ac3 follow debugger focus;
wenzelm
parents: 60869
diff changeset
   277
60854
8f45dd297357 more controls;
wenzelm
parents: 60842
diff changeset
   278
  def input(thread_name: String, msg: String*): Unit =
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   279
    session.protocol_command("Debugger.input", (thread_name :: msg.toList):_*)
60854
8f45dd297357 more controls;
wenzelm
parents: 60842
diff changeset
   280
60899
wenzelm
parents: 60898
diff changeset
   281
  def continue(thread_name: String): Unit = input(thread_name, "continue")
60869
878e32cf3131 more single stepping;
wenzelm
parents: 60863
diff changeset
   282
  def step(thread_name: String): Unit = input(thread_name, "step")
878e32cf3131 more single stepping;
wenzelm
parents: 60863
diff changeset
   283
  def step_over(thread_name: String): Unit = input(thread_name, "step_over")
878e32cf3131 more single stepping;
wenzelm
parents: 60863
diff changeset
   284
  def step_out(thread_name: String): Unit = input(thread_name, "step_out")
60856
eb21ae05ec43 clarified thread state;
wenzelm
parents: 60854
diff changeset
   285
60901
ce8abd005c5d clarified GUI event handling;
wenzelm
parents: 60900
diff changeset
   286
  def clear_output(thread_name: String)
ce8abd005c5d clarified GUI event handling;
wenzelm
parents: 60900
diff changeset
   287
  {
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   288
    state.change(_.clear_output(thread_name))
60902
9f185acfdcb8 clarified events;
wenzelm
parents: 60901
diff changeset
   289
    delay_update.invoke()
60901
ce8abd005c5d clarified GUI event handling;
wenzelm
parents: 60900
diff changeset
   290
  }
ce8abd005c5d clarified GUI event handling;
wenzelm
parents: 60900
diff changeset
   291
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   292
  def eval(c: Debugger.Context, SML: Boolean, context: String, expression: String)
60856
eb21ae05ec43 clarified thread state;
wenzelm
parents: 60854
diff changeset
   293
  {
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   294
    state.change(st => {
61014
39f67bb4e609 maintain per-thread focus context;
wenzelm
parents: 61011
diff changeset
   295
      input(c.thread_name, "eval", c.debug_index.getOrElse(0).toString,
61010
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
   296
        SML.toString, Symbol.encode(context), Symbol.encode(expression))
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   297
      st.clear_output(c.thread_name)
60896
625f2c8307da clarified output;
wenzelm
parents: 60889
diff changeset
   298
    })
60902
9f185acfdcb8 clarified events;
wenzelm
parents: 60901
diff changeset
   299
    delay_update.invoke()
60856
eb21ae05ec43 clarified thread state;
wenzelm
parents: 60854
diff changeset
   300
  }
60897
7aad4be8a48e print values for stack entry;
wenzelm
parents: 60896
diff changeset
   301
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   302
  def print_vals(c: Debugger.Context, SML: Boolean, context: String)
60897
7aad4be8a48e print values for stack entry;
wenzelm
parents: 60896
diff changeset
   303
  {
61014
39f67bb4e609 maintain per-thread focus context;
wenzelm
parents: 61011
diff changeset
   304
    require(c.debug_index.isDefined)
61010
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
   305
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   306
    state.change(st => {
61014
39f67bb4e609 maintain per-thread focus context;
wenzelm
parents: 61011
diff changeset
   307
      input(c.thread_name, "print_vals", c.debug_index.getOrElse(0).toString,
61010
cccfd7f6317d more explicit type Debugger.Context;
wenzelm
parents: 61008
diff changeset
   308
        SML.toString, Symbol.encode(context))
65213
51c0f094dc02 proper local debugger state, depending on session;
wenzelm
parents: 63805
diff changeset
   309
      st.clear_output(c.thread_name)
60897
7aad4be8a48e print values for stack entry;
wenzelm
parents: 60896
diff changeset
   310
    })
60902
9f185acfdcb8 clarified events;
wenzelm
parents: 60901
diff changeset
   311
    delay_update.invoke()
60897
7aad4be8a48e print values for stack entry;
wenzelm
parents: 60896
diff changeset
   312
  }
60749
f727b99faaf7 skeleton for interactive debugger;
wenzelm
parents:
diff changeset
   313
}