Как язык с поддержкой макросов отслеживает исходный код для отладки? - PullRequest
9 голосов
/ 09 июля 2010

Это более теоретический вопрос о макросах (я думаю). Я знаю, что макросы берут исходный код и создают объектный код без его оценки, что позволяет программистам создавать более универсальные синтаксические структуры. Если бы мне пришлось классифицировать эти две системы макросов, я бы сказал, что есть макрос "стиль С" и макрос "стиль Лисп".

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

Как отладчик отслеживает выполнение программы с точки зрения предварительно обработанного исходного кода? Существует ли специальный «режим отладки», который необходимо установить для сбора дополнительных данных о макросе?

В C я могу понять, что вы бы установили переключатель времени компиляции для отладки, но как интерпретируемый язык, такой как некоторые формы Lisp, сделает это?

Прошу прощения за то, что не попробовал это, но цепочка инструментов lisp требует больше времени, чем я должен потратить, чтобы выяснить.

Ответы [ 6 ]

3 голосов
/ 10 июля 2010

В LispWorks разработчики могут использовать Stepper tool .

LispWorks предоставляет степпер, где можно пройти полный процесс макроса расширения .

3 голосов
/ 09 июля 2010

Я не думаю, что есть принципиальная разница в макросах "стиль C" и "стиль Lisp" в том, как они компилируются.Оба преобразуют исходный код до того, как его увидит собственно компилятор.Большая разница в том, что макросы C используют препроцессор C (более слабый вторичный язык, который в основном предназначен для простой подстановки строк), а макросы Lisp написаны на самом Lisp (и, следовательно, могут делать все что угодно).

(какв сторону: я не видел нескомпилированный Лисп некоторое время ... конечно, не с начала века. Но если что-то интерпретировать, то кажется, что проблема отладки макросов легче, а не сложнее, так как у вас естьбольше информации.)

Я согласен с Майклом: я не видел отладчика для C, который вообще обрабатывает макросы.Код, использующий макросы, преобразуется до того, как что-то случится.Режим «отладка» для компиляции кода C обычно означает, что он хранит функции, типы, переменные, имена файлов и тому подобное - я не думаю, что кто-либо из них хранит информацию о макросах.

  • Для программ отладки, которые используют макросы , Lisp во многом похож на C: ваш отладчик видит скомпилированный код, а не приложение макроса.Обычно макросы сохраняются простыми и отлаживаются независимо перед использованием, чтобы избежать необходимости, как C.

  • Для отладки самих макросов перед тем, как вы приступитеи использовать его где-нибудь, Lisp имеет функции, которые делают это проще, чем в C, например, repl и macroexpand-1 (хотя в C, очевидно, есть способ макрорасширить весь файл полностью, сразу).Вы можете увидеть до и после макроразложения, прямо в вашем редакторе, когда вы пишете его.

Я не могу вспомнить ни разу, когда сталкивался с ситуацией, когда отладка в само определение макроса было бы полезно.Либо это ошибка в определении макроса, в этом случае macroexpand-1 немедленно изолирует проблему, либо ошибка ниже этого, и в этом случае обычные средства отладки работают нормально, и мне все равно, что макроразложение произошло между двумя кадрамимой стек вызовов.

2 голосов
/ 09 июля 2010

Вы действительно должны обратить внимание на ту поддержку, которую Racket имеет для отладки кода с помощью макросов.Эта поддержка имеет два аспекта, как упоминает Кен.С одной стороны, существует проблема отладки макросов: в Common Lisp лучший способ сделать это - просто развернуть формы макросов вручную.С CPP ситуация аналогична, но более примитивна - вы выполняете код только через расширение CPP и проверяете результат.Однако и того, и другого недостаточно для более вовлеченных макросов, и это послужило причиной наличия в Racket макро-отладчика - он показывает пошаговые инструкции по расширению синтаксиса с дополнительными указаниями на основе графического интерфейса длятакие вещи, как связанные идентификаторы и т. д.

На стороне с использованием макросов Racket всегда был более продвинутым, чем другие реализации Scheme и Lisp.Идея состоит в том, что каждое выражение (как синтаксический объект) представляет собой код плюс дополнительные данные, содержащие его исходное местоположение.Таким образом, когда форма является макросом, расширенный код, имеющий части, поступающие из макроса, будет иметь правильное исходное местоположение - из определения макроса, а не из его использования (где формы на самом деле отсутствуют).Некоторые реализации Scheme и Lisp будут реализовывать ограниченное для этого использование идентификаторов субформ, как упоминалось в dmitry-vk.

1 голос
/ 09 июля 2010

Обычно в C отладка на уровне источника имеет гранулярность строки (команда «next») или гранулярность уровня команды («step into»).Макропроцессоры вставляют в обработанный исходный код специальные директивы, которые позволяют компилятору отображать скомпилированные последовательности инструкций ЦП в строки исходного кода.

В Lisp не существует соглашения между макросами и компилятором для отслеживания исходного кода для сопоставления скомпилированного кода, поэтомуне всегда возможно выполнить пошаговое выполнение в исходном коде.

Очевидный вариант - выполнить пошаговое выполнение в макрорасширенном коде.Компилятор уже видит окончательную, расширенную версию кода и может отслеживать сопоставление исходного кода с машинным кодом.

Другой вариант - использовать тот факт, что выражения lisp во время манипуляции имеют идентичность.Если макрос прост и просто выполняет деструктурирование и вставку кода в шаблон, то некоторые выражения расширенного кода будут идентичны (в отношении сравнения EQ) выражениям, которые были прочитаны из исходного кода.В этом случае компилятор может отобразить некоторые выражения из расширенного кода в исходный код.

1 голос
/ 09 июля 2010

Я не знаю о макросах lisp (которые, я подозреваю, вероятно, сильно отличаются от макросов C) или об отладке, но многие - вероятно, большинство - отладчики C / C ++ не особенно хорошо справляются с отладкой на уровне исходного кода макросов препроцессора C.

Как правило, отладчики C / C ++ не «вступают» в определение макроса.Если макрос раскрывается в несколько операторов, то отладчик обычно просто остается в одной и той же исходной строке (где вызывается макрос) для каждой операции «шага» отладчика.

Это может сделать отладку макросов немного более болезненнойчем они могли бы быть - еще одна причина избегать их в C / C ++.Если макрос работает не совсем корректно, я перейду в режим сборки, чтобы отладить его или развернуть макрос (вручную или с помощью переключателя компилятора).Это довольно редко, что вы должны пойти на такой крайности;если вы пишете такие сложные макросы, вы, вероятно, выбрали неправильный подход.

0 голосов
/ 10 июля 2010

Простой ответ заключается в том, что это сложно ;-) Есть несколько разных вещей, которые способствуют возможности отладки программы, и даже больше для отслеживания макросов.

В C и C ++ препроцессориспользуется для расширения макросов и включения в реальный исходный код.Исходные имена файлов и номера строк отслеживаются в этом расширенном исходном файле с использованием директив #line.

http://msdn.microsoft.com/en-us/library/b5w2czay(VS.80).aspx

Когда программа на C или C ++ компилируется с включенной отладкой, ассемблер генерирует дополнительную информациюв объектном файле, который отслеживает исходные строки, имена символов, дескрипторы типов и т. д.

http://sources.redhat.com/gdb/onlinedocs/stabs.html

Операционная система имеет функции, позволяющие отладчику подключаться к процессу иконтролировать выполнение процесса;пауза, пошаговое выполнение и т. д.

Когда к программе подключен отладчик, он переводит стек процессов и счетчик программ обратно в символическую форму, просматривая значения адресов программ в информации отладки.

Динамические языки обычно выполняются на виртуальной машине, будь то интерпретатор или виртуальная машина с байт-кодом.Это виртуальная машина, которая предоставляет ловушки, позволяющие отладчику контролировать ход программы и проверять состояние программы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...