19.2.15.1 宏调用插桩

当 Edebug 对调用 Lisp 宏的表达式进行插桩时,需要该宏的额外信息才能正确完成工作。 这是因为无法仅凭宏调用本身判断其哪些子表达式是需要求值的形式(求值可能发生在宏体内部、宏展开结果求值时,或后续任意时机)。

因此,你必须为 Edebug 可能遇到的每个宏定义 Edebug 规范,以说明该宏调用的格式。 实现方式是在宏定义中添加 debug 声明。以下是为 for 示例宏指定规范的简单例子(see 宏参数的重复求值问题):

(defmacro for (var from init to final do &rest body)
  "Execute a simple \"for\" loop.
For example, (for i from 1 to 10 do (print i))."
  (declare (debug (symbolp "from" form "to" form "do" &rest form)))
  ...)

Edebug 规范用于标识宏调用中哪些部分是需要求值的表达式。 对于简单宏,规范通常与宏定义的形参列表非常相似,但规范的表达能力远强于宏参数。 关于 declare 形式的更多说明见 See 定义宏

请注意确保在插桩代码时,Edebug 能够识别对应的规范。 如果要插桩的函数使用了定义在其他文件中的宏,你可能需要先求值该函数所在文件中的 require 形式, 或显式加载包含该宏的文件。如果宏定义被 eval-when-compile 包裹,你可能需要手动求值该定义。

你也可以通过 def-edebug-spec 为宏单独定义 Edebug 规范,而不依赖宏定义本身。 对于 Lisp 编写的宏定义,添加 debug 声明是更推荐、更便捷的方式; 但 def-edebug-spec 使得为 C 实现的特殊形式定义 Edebug 规范成为可能。

Macro: def-edebug-spec macro specification

指定宏 macro 调用中的哪些表达式是需要求值的形式。 specification 应为 Edebug 规范,两个参数均不求值。

参数 macro 实际上可以是任意符号,不限于宏名。

以下表格列出 specification 的可选类型,以及每种类型对参数处理方式的说明:

t

所有参数均被插桩以支持求值。这是 (body) 的简写形式。

符号

该符号必须具有 Edebug 规范,Edebug 会使用该规范替代当前符号。 这种间接引用会持续到找到其他类型的规范为止,允许你从其他宏继承规范。

列表

列表元素描述调用形式中各参数的类型。规范列表的可选元素将在后续章节说明。

如果一个宏既没有通过 debug 声明,也没有通过 def-edebug-spec 调用定义 Edebug 规范, 则变量 edebug-eval-macro-args 将生效:

User Option: edebug-eval-macro-args

该变量控制 Edebug 处理无显式规范的宏参数的方式。 若值为 nil(默认),则不对任何参数进行求值插桩;否则,所有参数都会被插桩。


emacs

Emacs

org-mode

Orgmode

Donations

打赏

Copyright

© 2025 Jasper Hsu

Creative Commons

Creative Commons

Attribute

Attribute

Noncommercial

Noncommercial

Share Alike

Share Alike