本节介绍调试器内部使用的函数和变量。
该变量的值是用于调用调试器的函数。
其值必须是接受任意数量参数的函数,或更常见的是函数名。
该函数应触发某种调试器。变量的默认值为 debug。
Lisp 传递给该函数的第一个参数表示调用原因。
参数的约定在 debug 的说明中有详细描述(see 调用调试器)。
该函数打印当前活跃的 Lisp 函数调用跟踪信息。
输出的跟踪信息与 debug 在 *Backtrace* 缓冲区中显示的内容完全相同。
函数的返回值始终为 nil。
以下示例中,Lisp 表达式显式调用 backtrace。
这会将调用栈打印到流 standard-output,
本示例中该流对应缓冲区 ‘backtrace-output’。
调用栈的每一行代表一次函数调用。 如果函数的所有参数值均已确定,该行会显示函数名及参数值列表; 如果参数仍在计算中,该行则显示包含函数及其未求值参数的列表。 长列表或深度嵌套的结构可能会被省略。
(with-output-to-temp-buffer "backtrace-output"
(let ((var 1))
(save-excursion
(setq var (eval '(progn
(1+ var)
(list 'testing (backtrace))))))))
⇒ (testing nil)
----------- Buffer: backtrace-output ------------ backtrace() (list 'testing (backtrace))
(progn ...) eval((progn (1+ var) (list 'testing (backtrace)))) (setq ...) (save-excursion ...) (let ...) (with-output-to-temp-buffer ...) eval((with-output-to-temp-buffer ...)) eval-last-sexp-1(nil)
eval-last-sexp(nil) call-interactively(eval-last-sexp) ----------- Buffer: backtrace-output ------------
若该变量为非nil,调用栈中的每个栈帧都会以列表形式显示。
此举旨在提升调用栈的可读性,但代价是特殊形式与常规函数调用在视觉上不再有区别。
当 debugger-stack-frame-as-list 为非nil 时,上述示例的输出如下:
----------- Buffer: backtrace-output ------------ (backtrace) (list 'testing (backtrace))
(progn ...) (eval (progn (1+ var) (list 'testing (backtrace)))) (setq ...) (save-excursion ...) (let ...) (with-output-to-temp-buffer ...) (eval (with-output-to-temp-buffer ...)) (eval-last-sexp-1 nil)
(eval-last-sexp nil) (call-interactively eval-last-sexp) ----------- Buffer: backtrace-output ------------
若该变量为非nil,表示在下一次调用 eval、apply 或 funcall 前调用调试器。
进入调试器后,该变量 debug-on-next-call 会被设为 nil。
调试器中的 d 命令正是通过设置该变量实现功能。
该函数设置调用栈中向下数 level 层的栈帧的“退出时调试”标志,将其值设为 flag。
若 flag 为非nil,该栈帧后续退出时会触发调试器。
即使通过该栈帧进行非本地退出,也会进入调试器。
该函数仅由调试器内部使用。
该变量记录当前交互式命令的调试状态。
每次交互式调用命令时,该变量会被绑定为 nil。
调试器可设置该变量,为同一命令调用期间后续的调试器触发留存信息。
使用该变量而非普通全局变量的优势在于: 其数据不会延续到后续的命令调用中。
该变量已废弃,将在未来版本中移除。
函数 backtrace-frame 专为 Lisp 调试器设计使用。
它返回调用栈中向下数 frame-number 层的栈帧的计算状态信息。
如果该栈帧尚未求参数值,或属于特殊形式,返回值为 (nil function arg-forms…)。
如果该栈帧已完成参数求值并调用了函数,返回值为 (t function arg-values…)。
返回值中,function 是被求值列表的 CAR 部分,
若是宏调用则为 lambda 表达式。
如果函数包含 &rest 参数,该参数会表示为 arg-values 列表的尾部。
若指定了 base,则 frame-number 相对于 function 为 base 的最顶层栈帧计数。
若 frame-number 超出范围,backtrace-frame 返回 nil。
函数 mapbacktrace 会为调用栈中的每个栈帧调用一次 function,
起始位置为 function 等于 base 的第一个栈帧
(若省略 base 或其值为 nil,则从栈顶开始)。
调用 function 时传入四个参数:evald、func、args 和 flags。
如果栈帧尚未求参数值或属于特殊形式,evald 为 nil,args 为表达式列表。
如果栈帧已完成参数求值并调用了函数,evald 为 t,args 为值列表。
flags 是当前栈帧属性的属性列表(plist):
目前仅支持 :debug-on-exit 属性,
若栈帧的“退出时调试”标志已设置,则该属性值为 t。