Автоматизация перекомпиляции в среде emacs/slime live

Учитывая эту ситуацию:

(defmacro mac1 ...)

(defun func1 () 
  (mac1 ...))

Переопределение mac1 в живой среде не повлияет на func1, пока он сам не будет перекомпилирован.

Есть ли способ заставить emacs или lisp автоматически перекомпилировать func1 всякий раз, когда перекомпилируется mac1?

Что-то вроде этого в источнике было бы приемлемо:

(watch
  (defmacro mac1 ...))

(on-signal (mac1)
  (defun func1 ...))

Не так сложно реализовать, но я бы предпочел не изобретать колесо.


person BnMcGn    schedule 18.06.2016    source источник
comment
Не настоящий ответ, но если вы хотите взломать пакет cl, вы можете спрятать исходный код функции как свойство имени ее символа в оболочке вокруг defun и иметь вторую оболочку вокруг defmacro для просмотра who-macroexpands и повторения над этими спрятанными источниками. Или просто slime-compile-and-load-file, когда вы теряете представление о том, что могли сделать ваши изменения макроса.   -  person BRPocock    schedule 21.06.2016


Ответы (2)


Макросы не обязательно компилируются. Если вы используете SBCL (см. руководство), существует переменная с именем sb-ext:*evaluator-mode*, которую можно установить на :interpret, чтобы макрос расширялся во время оценки. Другие реализации могут предоставить что-то подобное. Это позволяет вам изменять определения макросов без перекомпиляции сайтов вызовов, как вы уже делаете с функциями.

Альтернативно, slime определяет функцию с именем slime-who-macroexpands. Вам придется немного покопаться, чтобы увидеть, как это работает, и, возможно, использовать его либо в среде Common Lisp (шикарно), либо на стороне emacs.

person coredump    schedule 18.06.2016

Например, в 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 хранит базу данных о звонках, можно перекомпилировать все функции, которые напрямую используют другие функции/макросы и зависят от них.

В редакторе есть команды Edit Callers и Continue Tags Search, чтобы найти вызывающие программы и затем перекомпилировать их вручную. Должно быть легко/возможно написать команду редактора, которая перекомпилирует все вызывающие программы.

person Rainer Joswig    schedule 19.06.2016
comment
Последний пример немного вводит в заблуждение, перекомпиляция уже скомпилированных функций не влияет на большинство реализаций, особенно на все текущие реализации, которые компилируются в собственный машинный код. Пожалуйста, добавьте примечание к примеру или перед ним. - person acelent; 21.06.2016
comment
NB. Аналог SBCL — sb-introspect:who-macroexpands…, а функция Slime — slime-who-macroexpands. Однако sb-introspect:who-macroexpands возвращает список символов и definition-source структур, и передача символа в compile не имеет никакого эффекта; вам, возможно, придется использовать definition-source-pathname или что-то еще, чтобы отследить его. - person BRPocock; 21.06.2016