支持宏的语言如何跟踪调试的源代码?

Sea*_*ods 9 c lisp macros language-implementation

这是一个关于宏的理论问题(我认为).我知道宏可以获取源代码并生成目标代码而无需对其进行评估,从而使程序员能够创建更多功能的语法结构.如果我必须对这两个宏系统进行分类,我会说有"C风格"宏和"Lisp风格"宏.

调试宏似乎有点棘手,因为在运行时,实际运行的代码与源代码不同.

调试器如何根据预处理的源代码跟踪程序的执行情况?是否有一个特殊的"调试模式"必须设置为捕获有关宏的额外数据?

在C中,我可以理解你为调试设置了一个编译时开关,但是解释语言(如某些形式的Lisp)会怎么做呢?

为不尝试这一点而道歉,但是lisp工具链需要的时间比我花费的时间要多.

Ken*_*Ken 4

我认为“C 风格”和“Lisp 风格”宏的编译方式没有根本区别。两者都会在编译器本身看到源代码之前对其进行转换。最大的区别是 C 的宏使用 C 预处理器(一种较弱的辅助语言,主要用于简单的字符串替换),而 Lisp 的宏是用 Lisp 本身编写的(因此可以做任何事情)。

(顺便说一句:我已经有一段时间没见过非编译的 Lisp 了……当然自世纪之交以来就没有见过。但如果有的话,被解释似乎会让宏调试问题变得更容易,而不是更困难,因为您有更多信息。)

我同意 Michael 的观点:我根本没有见过处理宏的 C 调试器。使用宏的代码会在发生任何事情之前进行转换。编译 C 代码的“调试”模式通常意味着它存储函数、类型、变量、文件名等——我不认为它们存储有关宏的信息。

  • 对于调试使用宏的程序,Lisp 与 C 几乎相同:调试器看到的是编译后的代码,而不是宏应用程序。通常,宏保持简单,并在使用前独立调试,以避免这种需要,就像 C 一样。

  • 为了调试宏 本身,在你去某个地方使用它之前,Lisp 确实具有比 C 中更容易的功能,例如 repl 和 macroexpand-1(尽管在 C 中显然有一种方法可以一次完全地宏扩展整个文件) )。当您编写宏扩展时,您可以在编辑器中看到宏扩展的前后情况。

我不记得任何时候我遇到过调试定义本身会很有用的情况。要么是宏定义中的错误,在这种情况下macroexpand-1立即隔离问题,要么是低于该错误的错误,在这种情况下,正常的调试工具工作正常,我不关心调用堆栈的两个帧之间发生宏扩展。