Macros 在公共Lisp中获取宏的堆栈跟踪模拟
我可能是在要求不可能的事情,但我还是想知道 是否可以获得宏的堆栈跟踪模拟?也就是说,如果在某个函数中设置了断点,宏堆栈跟踪将列出所有宏(可能包括它们的输入),这些宏经过宏扩展以在代码中达到该级别 据我所知,这目前是不可能的,但这可能是由于我的理解肤浅。Allegro或SBCL是否允许或跟踪此类信息?这似乎对调试宏非常有用 任何帮助或建议都将不胜感激。因为SBCL意味着所有代码都是自动编译的(而不是“解释的”)。对宏的调用作为编译的一部分进行了扩展,因此丢失了某个宏调用的事实Macros 在公共Lisp中获取宏的堆栈跟踪模拟,macros,common-lisp,stack-trace,trace,Macros,Common Lisp,Stack Trace,Trace,我可能是在要求不可能的事情,但我还是想知道 是否可以获得宏的堆栈跟踪模拟?也就是说,如果在某个函数中设置了断点,宏堆栈跟踪将列出所有宏(可能包括它们的输入),这些宏经过宏扩展以在代码中达到该级别 据我所知,这目前是不可能的,但这可能是由于我的理解肤浅。Allegro或SBCL是否允许或跟踪此类信息?这似乎对调试宏非常有用 任何帮助或建议都将不胜感激。因为SBCL意味着所有代码都是自动编译的(而不是“解释的”)。对宏的调用作为编译的一部分进行了扩展,因此丢失了某个宏调用的事实 (defmacro
(defmacro m (n)
`(/ 10 ,n))
(defun foo (x) (m x))
SBCL:
需要更多详细的选项,这显示了形式(block foo(mx))
:
当您(编译'foo)
时,宏调用将被展开(如SBCL),不再显示在回溯中(但Allegro的可能会有所帮助)
通常,在定义宏时,为了帮助调试,请尝试扩展到函数调用,而不是大型代码体。例如,代替:
(defmacro with-foo ((var-x var-y thing) &body body)
`(let ((,var-x (..derive from ,thing ..))
(,var-y (..derive from ,thing ..)))
,@body))
我会这样写:
(defmacro with-foo ((var-x var-y thing) &body body)
`(call-with-foo (lambda (,var-x ,var-y) ,@body) ,thing))
(defun call-with-foo (func thing)
(let ((x (..derive from thing ..)
(y (..derive from thing ..))
(funcall func x y)))
因此,它最终会出现在堆栈跟踪中,并且很容易重新定义。
见此:
顺便说一句,回到CL,你应该知道当我写这些
对于xxx宏,我几乎总是给它们打电话
这样我可以打任何一种电话。但我发现我几乎从未使用过
与xxx的通话,即使我是提供该选项的人。
我写它们的主要原因不是为了使用它们,而是为了
重新定义更容易,因为我可以用xxx重新定义调用,而不用
重新定义宏,因此如果
定义改变了
是的,AllegroCl支持宏的跟踪和一般调试。这是一个相当大的努力,不知道有多少好处,但弗兰兹倾向于做好事,使CL更可行。专业提示:有一个选项可以关闭我认为他们所谓的宏源代码级调试,如果您的代码大量使用宏,或者编译时间可能会变得疯狂,您将希望这样做。当您认为需要源代码调试时,只需重新打开它。注意,SBCL现在也有一个可选的解释器:@RainerJoswig您是否建议您可以使用可选的解释器来实现此目标?您考虑了哪些Allegro功能?我几乎只与Allegro合作,这对我来说是新闻。请注意,这只是一个关于步进的话题。我只是假设它们可以被追踪,等等。我自己从来不使用源代码调试器。我想我在堆栈跟踪中看到过宏。
[1] cl-user(6): :zoom :all t
Evaluation stack:
... 4 more newer frames ...
((:runsys "lisp_apply"))
[... sys::funcall-tramp ]
(excl::error-from-code 17 nil ...)
(sys::..runtime-operation "integer_divide" :unknown-args)
(excl::/_2op 10 0)
->(/ 10 0)
[... excl::eval-as-progn ]
(block foo (m x))
(foo 0)
(sys::..runtime-operation "comp_to_interp" 0)
[... excl::%eval ]
(eval (foo 0))
(defmacro with-foo ((var-x var-y thing) &body body)
`(let ((,var-x (..derive from ,thing ..))
(,var-y (..derive from ,thing ..)))
,@body))
(defmacro with-foo ((var-x var-y thing) &body body)
`(call-with-foo (lambda (,var-x ,var-y) ,@body) ,thing))
(defun call-with-foo (func thing)
(let ((x (..derive from thing ..)
(y (..derive from thing ..))
(funcall func x y)))