0

Emacs 版本:26.3
史莱姆版本:2.26.1


我启动 Emacs。

我打开一个简单的.lisp文件。

(defun testfn (x y)
  (+ x y))

(defmacro testmc (form)
  form
  `(list 1 2 3))

我将光标放在符号上defun并发出键盘命令M-.( slime-edit-definition)。

这应该让我想到defun.

但事实并非如此。

它把我带到这里:

在此处输入图像描述

我将光标放在符号上defmacro并发出键盘命令M-.( slime-edit-definition)。

这应该让我想到defmacro.

但事实并非如此。

它把我带到这里:

在此处输入图像描述

为什么会这样以及如何解决这个问题

4

2 回答 2

2

请注意,在尝试查找 的来源时,REPL 中有一个警告DEFUN

警告:不一致的 2 个表格编号翻译

您可以在 REPL 中自己复制它:

CL-USER> (let ((slynk::*buffer-package* (find-package :cl))
               (slynk::*buffer-readtable* *readtable*))
          (slynk:find-definitions-for-emacs "DEFUN"))
WARNING: inconsistent 2 form-number-translations
(("(DEFMACRO DEFUN)"
  (:LOCATION (:FILE "/home/chris/data/src/sbcl/src/code/macros.lisp")
   (:POSITION 4140)
   (:SNIPPET "(setq doc nil)
    (let* (;; stuff shared between LAMBDA and INLINE-LAMBDA and NAMED-LAMBDA
           (lambda-guts `(,@decls (block ,(fun-name-block-name name) ,@forms)))
           (lambda `(lambda ,lambda-list ,@lambda-guts))
           (named-lambda `("))))

要查找警告的来源,您可以像我一样先对存储库进行文本搜索,或者您可以使用以下更好的替代方法,即在警告时调用调试器:

(handler-bind ((warning (lambda (c) (invoke-debugger c))))
  (let ((slynk::*buffer-package* (find-package :cl))
        (slynk::*buffer-readtable* *readtable*))
    (slynk:find-definitions-for-emacs "DEFUN")))

这来自SLYNK-SBCL::FORM-NUMBER-POSITION,调试器中有趣的值是从 SBCL 获得的源位置:

#<SB-INTROSPECT:DEFINITION-SOURCE {10369C50F3}>
--------------------
The object is a STRUCTURE-OBJECT of type SB-INTROSPECT:DEFINITION-SOURCE.
PATHNAME: #P"SYS:SRC;CODE;MACROS.LISP"
FORM-PATH: (5)
FORM-NUMBER: 89
CHARACTER-OFFSET: 3917
FILE-WRITE-DATE: 3825178034
PLIST: NIL
DESCRIPTION: NIL

它说源是文件中的第五个顶层表单(对应于字符偏移),从这里开始,它FORM-NUMBER是表单的深度优先搜索遍历中的第 89 个表单(这来自结构的文档字符串)。

但是,如果我在 DEBUG 设置为 3 的情况下重新编译该函数FORM-NUMBER-POSITION,则在此位置读取的顶级表单 TLF为 NIL:

 1: (SLYNK-SBCL::FORM-NUMBER-POSITION #S(SB-INTROSPECT:DEFINITION-SOURCE :PATHNAME #P"SYS:SRC;CODE;MACROS.LISP" :FORM-PATH (5) :FORM-NUMBER 89 :CHARACTER-OFFSET 3917 :FILE-WRITE-DATE 3825178034 :PLIST NIL..
      Locals:
        DEFINITION-SOURCE = #S(SB-INTROSPECT:DEFINITION-SOURCE :PATHNAME #P"SYS:SRC;CODE;MACROS.LISP" :FORM-PATH (5) :FORM-NUMBER 89 :CHARACTER-OFFSET 3917 :FILE-WRITE-DATE 3825178034 :PLIST NIL :DESCRIPTION NIL)
        FORM-NUMBER = 89
        PATH-TABLE = #((0 0))
        POS-MAP = #<HASH-TABLE :TEST EQ :COUNT 126 {103B227EA3}>
        POS-MAP#1 = #<HASH-TABLE :TEST EQ :COUNT 126 {103B227EA3}>
        STREAM = #<SB-IMPL::STRING-INPUT-STREAM {7F3E0350D953}>
        TLF = NIL
        TLF#1 = NIL
        TLF-NUMBER = 5

read-source-form中,您可以看到该表单正在表单中被读取(ignore-errors (read ...)),如果出现错误,该表单将返回 NIL。我尝试(read ...)只调用,但这不知何故没有调用调试器,所以我做了与上面相同的事情并在任何情况下显式调用它。

有一个错误,即“SB-XC”包不存在,这是意料之中的,因为如果我没记错的话,这是一个只在SBCL本身编译期间存在的包。

我认为你应该联系SBCLSLY 开发人员并为此直接提交错误,他们肯定会更好地了解如何修复该行为(除了提供错误报告的通常详细信息外,请随时链接到您的问题)。

于 2021-10-23T22:40:24.857 回答
1

我看到的和你看到的差不多。

Defun(defboot.lisp 的第 280 行)是一个宏,它是根据您所看到的 defun-expander(defboot.lisp 的第 230 行)定义的。

然而,defmacro 将您直接带到它的定义(defmacro.lisp 的第 15 行),这就是您所看到的。

它似乎在做有用的事情。

我定义了一个新函数'addmore'

(defun addmore (x y z)
  (testfn x (testfn y z)))

我把它全部编译了,然后M-。在“addmore”上,我看到了 testfn 的定义。

所以我认为这一切都有效。

于 2021-10-23T14:37:14.580 回答