Описание отладчика HomeLisp

Не будет сильным преувеличением сказать, что программирование в среде, которая не содержит отладочных средств есть программистский экстрим. Поэтому все "хорошие" среды разработки поддерживают отладку. Причем, некоторые отладчики представляют собой поистине величественные здания. Так, например, отладчик известной системы LispWorks просто подавляет своими возможностями неискушенного пользователя.

Реализуюя свой отладчик, разработчик HomeLisp ставил перед собой достаточные скромные задачи: нужно, чтобы можно было "отловить" вызов функции и изменение значения символа. "Отловить" - значит остановить вычисления и увидеть состояние текущих контекстов. Кроме этого желательна возможность выполнить "локальные вычисления" в точке останова. Необходима также возможность продолжения останвленных вычислений. Все побочные эффекты отлаживаемого кода (включая вывод функциями PRINT и родственными ей) не должны нарушаться.

Насколько все это удалось реализовать судить читателю и пользователю HomeLisp.


Запуск и остановка отладчика

Отладчик HomeLisp доступен только при работе в IDE. Активизировать отладчик можно двумя способами: вызовом функции DEBUG или посредством нажатия кнопки на панели инструментов (выбора соответствующего пункта главного меню). Кнопка вызова отладчика на панели инструментов IDE показана ниже:

Главное окно отладчика имеет вид:

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

Тулбар содержит семь кнопок. Четвертая, пятая и шестая кнопки при начале работы с отладчиком изначально неактивны. Ниже тулбара размещается многострочная область ввода. Если ввести в эту область ввода S-выражение, то четвертая и пятая кнопки тулбрара станут активными:

Шестая кнопка тулбара бывает активной только в процессе вычисления. Ниже назначение всех кнопок тулбара будет описано более подробно.

Кнопка Выполняемое действие
Задать точку останова при входе в заданную функцию.
Задать точку останова при изменении значения заданного символа.
Вычислить произвольное вводимое S-выражение в текущем контексте.
Выполнить один шаг (одно вычисление EVAL) и остановиться.
Вычислять в автоматическом режиме. Если предварительно не было задано точек останова, то вычисления остановятся либо при возникновении ошибки, либо когда исходное S-выражение будет вычислено.
Остановить вычисления. В режиме ожидания кнопка неактивна.
Закрыть отладчик и вернуться в среду разработки.

Для завершения работы с отладчиком следует нажать кнопку с изображением черной стрелки; окно отладки закроется и отобразится главное окно среды разработки. Если запущен процесс выполнения в автоматическом режиме, то его можно прервать, нажав кнопку прерывания (на ней изображены две вертикальные стрелки).

Задание точки останова при входе в функцию

Для задания точек останова при входе в нужные функции следует щелкнуть по первой слева кнопке тулбара. Будет отображено окно задания точки останова:

Окно включает список с чекбоксами, содержащий все функции Лисп-машины на момент запуска отладчика. Имена функций упорядочены по алфавиту, а слева от имени в скобках показан тип функции. Пользователь может, листая список, найти нужную функцию и отметить ее чекбокс. Для облегчения поиска функции можно ввести ее имя (или часть имени) в область ввода и нажать ENTER (или щелкнуть по кнопке с изображением одного треугольника). Будет подведена первая функция списка, в имени которой содержатся (в любой позиции) введенные символы:

Для продолжения поиска следует щелкнуть по кнопке с изображением двух треугольников. Будет подведено следующее имя, удовлектворяющее условию поиска. Отметив все нужные функции, следует выйти из режима, щелкнув по крайней правой кнопке (на ней изображена черная стрелка).

Установим точку останова при входе в функцию DIFFERENCE, выйдем из режима установки точек останова и запустим выполнение в автоматическом режиме (нажав соответствующую кнопку). Через секунду увидим следующую картинку:

Что означает эта картинка? Произошёл останов при входе в DIFFERENCE. Текущий лексический контекст содержит переменную x со значением 3. Если еще раз нажать кнопку автоматического выполнения, то будет произведен останов при выходе из DIFFERENCE, результат вычисления будет равен, естественно, двум:


Таким образом, можно "прощелкать" все вызовы функций.

Вычисления в текущем контексте

Когда вычисления остановлены, пользователь может выполнить любые вычисления в текущих контекстах (лексическом и глобальном). Для этого следует сначала щелкнуть по третьей кнопке тулбара главной формы отладчика. Будет отображено окно "Вычислить в текущем контексте". На этом окне расположен тулбар с тремя кнопками, область ввода выражения и область ответа. Пользователь вводит S-выражение в область ввода и щелкает по первой кнопке тулбара ("Вычислить"). В области ответа появляется результат:

Легко убедиться, что результат верен (вычисления велись в лексическом контексте, в котором x=2. Вторая кнопка тулбара окна "Вычислить в текущем контексте" служит для очистки областей ввода и результата.

Если в процессе вычисления S-выражения призойдет ошибка, то пользователю будет выведен результат ERRSTATE, но основные вычисления могут быть продолжены. Так, если после возникновении ошибки, показанной на рисунке ниже

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

Задание точки останова при изменении значения символа

Другая возможность отладчика обеспечивает останов вычислений при изменении значения заданного символа. Чтобы задействовать эту возможность следует щелкнуть по второй кнопке тулбара главной формы отладчика (на кнопке изображен котёнок). Будет отображено окно "Наблюдение":

Чтобы вызвать останов вычислений при изменении значения символа следует задать этот символ в поле ввода "Добавляемый символ" и нажать кнопку с красным плюсом. Символ будет перенесен из области ввода в список символов (расположенный ниже). При попытке добавить символ повторно добавления не происходит, а выводится предупреждение.

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

При останове доступна возможность вычисления в текущем контексте (описанная выше).

Для примера рассмотрим вычисление S-выражения:

(prog (i) (for i 1 5 ((printline i))))

Добавим символ i к списку отслеживаемых символов и запустим вычисление в автоматическом режиме. Всякий раз, когда значение символа i будет меняться отладчик будет останавливаться: