nuget server logo nuget api documents
↑

API Docs / REnv / DebuggerContext

DebuggerContext

Full name SMRUCC.Rsharp.Interpreter.DebuggerContext Assembly REnv Members 28

调试器状态管理类

00 Remarks

这个类型是整个调试器的核心, 其内部不包含任何的控制台交互代码, 控制台的交互逻辑位于 ConsoleDebuggerFrontend 之中, 使得GUI宿主程序能够通过订阅 DebuggerContext.OnBreakpointHit 事件 并且调用 DebuggerContext.Resume() 函数的方式来复用同一套调试器内核.

在整个环境链之上, 所有的 Environment 对象都是共享 同一个 DebuggerContext 实例的, 请参见 Environment 的构造函数之中的相关实现

01 Syntax

SMRUCC.Rsharp.Interpreter.DebuggerContext

02 Methods

NameOverloadsSummary
Start 1 启动调试会话
Stop 1 结束调试会话, 让脚本程序继续正常的执行下去
EnterBlock 1 进入一个新的代码块
ExitBlock 1 离开当前的代码块
ShouldPause 1 检查是否应该暂停执行
TryHitBreakpoint 1 判断当前的表达式之上是否命中了某一个断点
evaluateCondition 1 对条件断点的条件表达式进行求值
Pause 1 进入暂停状态, 等待用户的指令
Resume 1 设置下一步的调试动作并且唤醒被阻塞住的执行线程
EvaluateWithoutDebug 1 在临时挂起调试状态的情况下执行一段R#程序
AddBreakpoint 1 添加一个断点
RemoveBreakpoint 1 移除掉指定位置上的断点
SetEnabled 1 设置指定位置上的断点的启用状态
ClearBreakpoints 1 清除掉所有的断点
ListBreakpoints 1 列出当前所注册的全部的断点

03 Properties

NameOverloadsSummary
breakpoints 1 断点的集合管理器
inspector 1 运行时的检查器, 提供查看变量/调用堆栈以及表达式求值等功能
CurrentAction 1 当前的调试动作
IsDebugging 1 是否处于调试模式?
CurrentEnvironment 1 用于外部(例如UI界面)访问当前的变量环境
stackDepth 1 当前的代码块嵌套深度
isOwnerThread 1 当前的调用是否发生在主线程之上?

04 Fields

NameOverloadsSummary
_depth 1 DebuggerContext.stackDepth 的后备字段
baselineDepth 1 在执行单步操作的时候所记录下来的基准深度
resumeSignal 1 用于阻塞执行线程的信号量
ownerThreadId 1 创建这个调试器上下文对象的线程的编号

05 Events

NameOverloadsSummary
OnBreakpointHit 2 触发断点时的回调事件(可以用来弹窗或者在控制台之中做交互)

06 Members

method Start #
Start(Boolean)

启动调试会话

Parameters
NameTypeDescription
breakOnEntryBoolean

是否在脚本的第一条语句处就暂停下来? 默认为True, 便于用户在脚本开始执行之前设置断点

method Stop #
Stop

结束调试会话, 让脚本程序继续正常的执行下去

method EnterBlock #
EnterBlock

进入一个新的代码块

Remarks

这个函数只应该被 ExecutableLoop.Execute() 所调用

method ExitBlock #
ExitBlock

离开当前的代码块

Remarks

这个函数只应该在 ExecutableLoop.Execute() 的 Finally 代码块之中被调用, 以保证在发生了异常或者是通过 return/break 提前退出的时候深度计数器不会失衡

method ShouldPause #

检查是否应该暂停执行

Parameters
NameTypeDescription
exprExpression

当前即将被执行的表达式

envEnvironment

当前的运行时环境

hitBreakpoint

如果本次暂停是由断点所触发的话, 则通过这个参数返回对应的断点对象

method TryHitBreakpoint #
TryHitBreakpoint(Expression, Environment)

判断当前的表达式之上是否命中了某一个断点

method evaluateCondition #
evaluateCondition(Breakpoint, Environment)

对条件断点的条件表达式进行求值

Returns

当条件表达式的求值过程之中发生了错误的时候, 这个函数会返回True(即安全失败, 仍然中断执行), 避免因为条件表达式本身存在问题而导致断点被静默的忽略掉

method Pause #
Pause(DebugFrame)

进入暂停状态, 等待用户的指令

Remarks

这是一个阻塞调用. 函数会先触发 DebuggerContext.OnBreakpointHit 事件 来通知宿主程序更新其变量监视界面, 然后阻塞住当前的执行线程, 直到宿主程序调用了 DebuggerContext.Resume() 为止

method Resume #
Resume(DebugAction)

设置下一步的调试动作并且唤醒被阻塞住的执行线程

Remarks

这个函数是由宿主程序或者是控制台前端所在的线程来调用的

Parameters
NameTypeDescription
actionDebugAction

下一步所要执行的调试动作

method EvaluateWithoutDebug #
EvaluateWithoutDebug(Program, Environment)

在临时挂起调试状态的情况下执行一段R#程序

Remarks

在暂停点上对监视表达式或者是条件断点的条件表达式进行求值的时候, 其内部同样会经由 ExecutableLoop.Execute() 来执行, 如果不做特殊处理的话就会再一次的触发暂停逻辑, 从而使得执行线程重入 DebuggerContext.Pause() 而造成死锁.

所以在这里通过临时的将 DebuggerContext.IsDebugging 置为False 的方式来保证求值过程本身不会被调试器所拦截

method AddBreakpoint #
AddBreakpoint(String, Int32, String)

添加一个断点

Parameters
NameTypeDescription
fileString

脚本文件的路径

lineInt32

源代码的行号

conditionString

可选的条件表达式R#源代码

method RemoveBreakpoint #
RemoveBreakpoint(String, Int32)

移除掉指定位置上的断点

method SetEnabled #
SetEnabled(String, Int32, Boolean)

设置指定位置上的断点的启用状态

method ClearBreakpoints #
ClearBreakpoints

清除掉所有的断点

method ListBreakpoints #
ListBreakpoints

列出当前所注册的全部的断点

property breakpoints #
breakpoints

断点的集合管理器

property inspector #
inspector

运行时的检查器, 提供查看变量/调用堆栈以及表达式求值等功能

property CurrentAction #
CurrentAction

当前的调试动作

property IsDebugging #
IsDebugging

是否处于调试模式?

Remarks

当这个属性值为False的时候, 程序的执行不会受到调试器的任何影响, 在 ExecutableLoop 的热点循环之中仅存在一次布尔判断的开销

property CurrentEnvironment #
CurrentEnvironment

用于外部(例如UI界面)访问当前的变量环境

property stackDepth #
stackDepth

当前的代码块嵌套深度

Remarks

因为所有的函数体/循环体/分支体最终都是通过 ExecutableLoop.Execute() 来执行其内部的语句列表的, 所以在该函数的出入口处对这个计数器做自增自减操作之后, 这个计数器的数值就天然的等于当前的代码块的嵌套深度了

property isOwnerThread #
isOwnerThread

当前的调用是否发生在主线程之上?

field _depth #
_depth
Remarks

因为需要通过 Interlocked 来进行原子操作, 所以在这里必须要声明为一个可以按引用传递的字段

field baselineDepth #
baselineDepth

在执行单步操作的时候所记录下来的基准深度

field resumeSignal #
resumeSignal

用于阻塞执行线程的信号量

Remarks

初始状态为无信号, 使得 DebuggerContext.Pause() 能够阻塞住执行线程, 直到宿主程序调用 DebuggerContext.Resume() 将其置位为止

field ownerThreadId #
ownerThreadId

创建这个调试器上下文对象的线程的编号

Remarks

因为 DebuggerContext 在整个环境链之上是共享的同一个实例, 而 parLapply/parSapply/%dopar% 等并行操作会在多个工作线程之上同时执行 R#的表达式, 如果不加以限制的话, 多个工作线程会同时在这里等待同一个信号量 而造成死锁. 所以在这里记录下创建者线程(即主线程)的编号, 使得只有主线程才会真正的进入暂停状态

event OnBreakpointHit #
OnBreakpointHit

触发断点时的回调事件(可以用来弹窗或者在控制台之中做交互)

Remarks

这个事件是在执行线程之上被同步触发的, 事件的处理程序返回之后, 执行线程会继续阻塞在 DebuggerContext.Pause() 之中, 直到有其他的代码调用了 DebuggerContext.Resume() 为止

event OnBreakpointHit overload 2 #
OnBreakpointHit