Автоматизация перекомпиляции в среде emacs/slime
Учитывая эту ситуацию:
(defmacro mac1 ...)
(defun func1 ()
(mac1 ...))
Переопределение mac1
в живую среду не повлияет func1
пока он сам не перекомпилируется.
Есть ли способ получить emacs или lisp для автоматической перекомпиляции func1
всякий раз, когда mac1
перекомпилируется?
Нечто подобное в источнике будет приемлемым:
(watch
(defmacro mac1 ...))
(on-signal (mac1)
(defun func1 ...))
Не так сложно реализовать, но я бы предпочел избежать повторного изобретения колес.
2 ответа
Макросы не обязательно компилируются. Если вы используете SBCL (см. Руководство), существует переменная с именем sb-ext:*evaluator-mode*
который может быть установлен на :interpret
так что макрос расширяется во время оценки. Другие реализации могут предоставить нечто подобное. Это позволяет вам изменять определения макросов, не перекомпилируя сайты вызовов, как вы уже сделали с функциями.
В качестве альтернативы, slime определяет функцию с именем slime-who-macroexpands
, Вам нужно немного покопаться, чтобы увидеть, как это работает, и, возможно, использовать это, либо в среде Common Lisp (swank), либо на стороне emacs.
Например, в LispWorks вы можете сделать следующее. Вероятно, у SBCL есть подобное средство.
Допустим, у нас есть это:
(defmacro foo ()
`(list 1 2 3))
(defun bar () (first (foo)))
(defun baz () (second (foo)))
Теперь вы можете спросить, кто звонит foo
:
CL-USER 11 > (who-calls 'foo)
(BAZ BAR)
Это позволяет легко перекомпилировать обе функции:
CL-USER 12 > (mapcar 'compile (who-calls 'foo))
;;;*** Warning in BAZ: The definition of BAZ is already compiled.
;;;*** Warning in BAR: The definition of BAR is already compiled.
(BAZ BAR)
Поскольку LispWorks хранит базу данных who-звонков, можно перекомпилировать все функции, которые непосредственно используют и зависят от других функций / макросов.
Редактор имеет команду Edit Callers
а также Continue Tags Search
чтобы найти абонентов, а затем перекомпилировать их вручную. Должно быть легко / возможно написать команду редактора, которая перекомпилирует всех вызывающих.