У меня странная ошибка компилятора SBCL, может быть, кто-нибудь объяснит мне, что там происходит. Для информации в пакете используются optima и drakma. Я действительно пытался минимизировать опубликованный код, но эта сумма требовалась для понимания проблемы.

(defun signal-vk-error (code)
  (error ;; <--- HERE IS THING
    (case code
      (100 'parse-error)
      (otherwise 'error))))

(defmacro match-with-error (response matcher)
  `(match ,response
         ((alist (:ERROR . code))
          (signal-vk-error code))
         ,matcher))

(defun api-call-response (resp)
  (match-with-error
    resp
    ((alist (:RESPONSE . data)) data)))

Скомпилировав этот файл, я получил:

; caught ERROR:
;   don't know how to dump CODE (default MAKE-LOAD-FORM method called).
Unhandled TYPE-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING
                                  {1002BF6F03}>:
  The value NIL is not of type (AND ATOM (NOT NULL)).

Итак, похоже, что sbcl (1.2.4) не может создать двоичное представление, но я не могу понять почему.

Если я просто изменю ERROR на SIGNAL в signal-vk-error - все компилируется, загружается и работает должным образом. Я также могу просто загрузить файл в слизь и eval, он будет работать без ошибок и предупреждений.

Итак, вопрос в том, что не так с error? В чем основное различие между error и signal?

ОБНОВЛЕНИЕ 1: Интересное наблюдение: если я удалю функцию signal-vk-error и просто помещу этот код в определение макроса, он будет скомпилирован нормально.

ОБНОВЛЕНИЕ 2: благодаря @RainerJoswig объявление signal-vk-error не встроенным решает проблему. Сообщено команде SBCL, похоже, они проводят некоторую оптимизацию, которая в данном случае прерывает компиляцию .

1
coredump 7 Окт 2014 в 19:56
1
Откуда берется переменная кода? Используйте macroexpand, чтобы увидеть, во что расширяется макрос.
 – 
Rainer Joswig
7 Окт 2014 в 20:24
Я попытался. optima:match просто привязывает код переменной к значению указанного места в списке, если оно есть. Макрорасширение на самом деле не дает никакой подсказки (не хочу публиковать здесь длинный код). В любом случае, error вызывается внутри определения функции, если есть какие-то проблемы с переменными, почему помогает замена error на signal? Это не должно.
 – 
coredump
7 Окт 2014 в 20:29
1
Удалите дракму... Поскольку ПОИСКПОЗ кажется макросом, вам действительно нужно посмотреть, что он делает и что создает.
 – 
Rainer Joswig
7 Окт 2014 в 20:44
1
Может быть проблема SBCL 1.2.4. В более ранней версии вроде работает.
 – 
Rainer Joswig
7 Окт 2014 в 21:56
1
Если вы объявите вызов ошибки не встроенным, он сработает.
 – 
Rainer Joswig
7 Окт 2014 в 22:05

2 ответа

Лучший ответ

Как выяснилось, проблема в компиляторе, фактически их две, одна из которых якобы является фичей. Любой желающий может прочитать беседу между одним из хакеров SBCL и автором optima в багтрекере .

На данный момент это исправлено на стороне optima, поскольку объект шаблона не раскрывается во время макросъемки, commit d7ec49d7d7d7ecf2d7d7d7ecf7d7d7e6

0
coredump 15 Окт 2014 в 20:37

Наименьший способ воспроизвести проблему:

(defun signal-vk-error ()
  (error 'error))

(defun api-call-response ()
  (optima:match 1
    ((not 2)
     (signal-vk-error))))

Если я макрорасширяю или прохожу форму match, проблема исчезает.

Следующее также заставляет проблему исчезнуть.

(declaim (notinline error))
1
Rainer Joswig 7 Окт 2014 в 23:23
Спасибо. Это проще. Я изменил код в отчете об ошибках. Также проверил с помощью CCL - компилируется без объявления.
 – 
coredump
7 Окт 2014 в 23:35