воскресенье, 14 марта 2010 г.

Расширение возможностей SLIME 2

Продолжаю экспериментировать над расширением возможностей SLIME. В прошлый раз, я указывал, что можно переопределить поведение стандартного инспектора объектов для собственных классов с помощью специальной реализации generic-функции swank:emacs-inspect . Использую эту возможность я создал достаточно интересные инспекторы модулей и виртуальных хостов (что получается расскажу в следующий раз). Но мне не нравился один момент. В инспекторе модуля я показываю список маршрутов (routes), предоставляемых модулем. В RESTAS маршруты определяются через макрос define-routes, который просто создаёт символ и настраивает его свойства. Таким образом, маршрут это фактически просто символ. Что бы в инспекторе объектов он отображался именно как маршрут (а для символов swank:emacs-inspect уже определена) я создал отдельную структуру-обёртку %restas-route. Всё бы хорошо, но стандартная функция инспектора slime-inspector-show-source (вызывается по нажатию ".") показывает на маршруте именно определение этой структуры, а я хотел бы, что бы эта команда открывала соответствующее определение define-rotue - было бы чрезвычайно удобно. При чём, технически такая возможность безусловно есть, ибо define-route также создаёт одноимённую функцию (которая является обработчиком маршрута) и таким образом компилятор (ну если он вообще поддерживает такую возможность) знает место определения. Очень быстро я определил, что соответствующее поведение обеспечивается функцией swank-backend:find-source-location, которая принимает объект, а возвращает (ну если реализация это позволяет) его местоположение в исходном коде. Но это простая функция, при чем, по разному реализуемая в разных бэкэндах и изменить её поведение несколько затруднительно. Поэтому я ввёл новую generic-функцию swank:object-source-location, которая по-умолчанию, просто вызывает find-source-location, но поведение которой можно изменить для своих объектов, и заменил в swank.lisp вызовы find-source-location (благо, таких мест оказалось целых два) на вызовы этой новой функции. Теперь реализация нужного поведения оказалась тривиальной:
(defstruct %restas-route
symbol)

(defmethod swank:object-source-location ((route %restas-route))
(swank:object-source-location (symbol-function (%restas-route-symbol route))))

3 комментария:

  1. Делать call-next-method и менять при этом тип аргументов - очень плохо.

    "When providing arguments to call-next-method, the following rule must be satisfied or an error of type error should be signaled: the ordered set of applicable methods for a changed set of arguments for call-next-method must be the same as the ordered set of applicable methods for the original arguments to the generic function. Optimizations of the error checking are possible, but they must not change the semantics of call-next-method. "

    ОтветитьУдалить
  2. @dmitry-vk
    Хм, спасибо, переделаю, и буду иметь в виду, но как-то пока никаких проблем не встречал :(

    ОтветитьУдалить
  3. Вокруг restas постепенно образовывается инфраструктура... Вот интересно, в перспективе вырисовывается админка сайта, написанная на elisp - было бы весьма Ъ..

    ОтветитьУдалить